首先部署pod
使用原先的deployment的资源清单进行部署。

[kubeadm@server1 ~]$ kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP            NODE      NOMINATED NODE   READINESS GATES
nginx-deployment-7d6f48b859-5rsrm   1/1     Running   0          61s   10.244.3.17   server4   <none>           <none>
nginx-deployment-7d6f48b859-f5zmh   1/1     Running   0          61s   10.244.2.17   server3   <none>           <none>
nginx-deployment-7d6f48b859-n9lzd   1/1     Running   0          61s   10.244.0.23   server1   <none>           <none>

这时候每个节点他会自动暴露出一个ip地址,但是这个时候外部并不能进行访问pod内部,只能在节点内部进行查看。但是使用ip访问,每个ip都是独立的,是否可以使用公共ip访问三个pod节点呢?
那就要使用service服务来创建一个vip,顺便也实现了负载均衡。
service的类型分为:
ClusterIP:系统自动分配的虚拟ip只能访问内部集群。
NodePort:将node端口主动暴露
LoadBalancer:创建一个外部的负载均衡 (收费)
ExternalName:通过DNS Cname转发

ClusterIP

apiVersion: v1
kind: Service 
metadata:
  name: svc-nginx
spec:
  ports:
    - name: http
      port: 80 
      targetPort: 80
  selector: ##选择标签是app为nginx的
      app: nginx
[kubeadm@server1 ~]$ kubectl create -f svc-nginx.yaml 
service/svc-nginx created
[kubeadm@server1 ~]$ kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   4d1h
svc-nginx    ClusterIP   10.106.48.183   <none>        80/TCP    21s

创建完成就主动将ip暴露出来了,这个ip是集群自动分配的。这样直接使用暴露出来的ip进行访问,三个集群就可以自动负载均衡。
再创建一个交互式pod,进入这个pod中也可以访问上面作负载均衡的三个pod,并且ClusterIP还自带DNS解析功能,在交互式pod的内部就可以直接使用名称进行访问。我们对集群进行查看就可以看到有两个dns。

[kubeadm@server1 ~]$ kubectl get deployments.apps -n kube-system 
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
coredns   2/2     2            2           4d2h

service是由kube-proxy和iptables一起实现的。但是当有很多pod时,iptables会不断的刷新策略,这就消耗很多的资源,所以除了这种方法还有一种可以支持大量pod的方案,ipvs模式的service。
使用ipvs首先需要安装ipvsadm。
但是安装之后并没有使用这个ipvs,因为使用的时候需要将这个ipvs的模块进行激活操作,如何激活,一般我们是更新kube-proxy的配置文件达到激活的目的。
使用命令

kubectl -n kube-system edit cm kube-proxy

进入文件修改后定位mode,将mode模式改为ipvs

mode: "ipvs"

这时候编辑完了以后文件是不生效的,生效需要将原有的pod杀死后,因为控制器的缘故,会自动生成新的pod,这时候文件才会生效。

kubectl get pod -n kube-system -o wide | grep kube-proxy |awk '{system("kubectl delete pod "$1" -n kube-system")}'

重建pod完成后策略即可刷新

[root@server3 docker]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.96.0.1:443 rr
  -> 192.168.122.2:6443           Masq    1      0          0         
TCP  10.96.0.10:53 rr
  -> 10.244.0.24:53               Masq    1      0          0         
  -> 10.244.0.26:53               Masq    1      0          0         
TCP  10.96.0.10:9153 rr
  -> 10.244.0.24:9153             Masq    1      0          0         
  -> 10.244.0.26:9153             Masq    1      0          0         
TCP  10.106.48.183:80 rr
  -> 10.244.0.25:80               Masq    1      0          0         
  -> 10.244.2.22:80               Masq    1      0          0         
  -> 10.244.3.21:80               Masq    1      0          0         
UDP  10.96.0.10:53 rr
  -> 10.244.0.24:53               Masq    1      0          0         
  -> 10.244.0.26:53               Masq    1      0          0

但是即使策略刷新了iptables也不能关闭,因为还有别的用处,不仅仅只有service使用。

nodeport

apiVersion: v1
kind: Service
metadata:
  name: svc-nginx-2
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
      app: nginx
  type: NodePort

首先编写资源清单,其中最重要的是最后一行的type。type的模式设置为NodePort
创建完成后将会给你暴露出一个端口。

[kubeadm@server1 ~]$ kubectl get svc
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
svc-nginx-2   NodePort    10.111.255.157   <none>        80:30360/TCP   14s

端口暴露后,使用命令进行访问

[root@localhost ~]# curl 192.168.122.4:30360
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@localhost ~]# curl 192.168.122.4:30360
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@localhost ~]# curl 192.168.122.4:30360
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

可以访问到,而且在查看的时候可以看到已经实现了负载均衡。

[root@server3 docker]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.122.4:30360 rr
  -> 10.244.0.25:80               Masq    1      0          1         
  -> 10.244.2.22:80               Masq    1      0          2         
  -> 10.244.3.21:80               Masq    1      0          2

ExternalName

说白了ExternalName就是一个DNS。用来作解析功能。下来首先进行设置。
第一步编写资源清单,这个资源清单十分的少,不用指定端口什么的,要指定的只有模式再指定一个域名即可使用。

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
spec:
  type: ExternalName
  externalName: test.passyt.com

创建完成后我们查看svc

[kubeadm@server1 ~]$ kubectl get svc
NAME          TYPE           CLUSTER-IP       EXTERNAL-IP       PORT(S)        AGE
my-nginx      ExternalName   <none>           test.passyt.com   <none>         6s

他并没有和别的svc一样显示ip ,而是显示我们设置的域名。那我们应该怎么使用呢?
首先查看CLUSTER-IP

[kubeadm@server1 ~]$ kubectl get svc -n kube-system 
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   4d7h

再来使用A记录来查看。

[kubeadm@server1 ~]$ dig -t A test.passyt.com @10.96.0.10

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> -t A test.passyt.com @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 38011
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;test.passyt.com.		IN	A

;; AUTHORITY SECTION:
com.			30	IN	SOA	a.gtld-servers.net. nstld.verisign-grs.com. 1582207923 1800 900 604800 86400

;; Query time: 2699 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: 四 2月 20 22:12:20 CST 2020
;; MSG SIZE  rcvd: 123

service还可以设置分配一个公有的ip
第一步还是编写资源清单,但是用之前的也可以,不同点在于externalIPs
这个选项。

piVersion: v1
kind: Service
metadata:
  name: svc-2
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
      app: nginx
  externalIPs:
    - 192.168.122.100
[kubeadm@server1 ~]$ kubectl apply -f service.yaml 
service/svc-2 configured
[kubeadm@server1 ~]$ kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP       PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>            443/TCP   5d2h
svc-2        ClusterIP   10.103.181.74   192.168.122.100   80/TCP    3m14s

这样已经设置出来一个对外的ip,外部使用这个ip就可以直接访问到pod中。

[root@localhost ~]# curl 192.168.122.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@localhost ~]# curl 192.168.122.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@localhost ~]# curl 192.168.122.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>