k8s-学习笔记2-容器部署nginx负载均衡

deployment文件部署

# cat nginx_deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - image: nginx
          imagePullPolicy: Always
          name: nginx
      imagePullSecrets:
        - name: default-secret

  

部署完成后,查看pod信息,可以看到两个pod的ip,和所在的node。

# kubectl get pods -l app=nginx -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE                          NOMINATED NODE   READINESS GATES
nginx-645ccd8dc9-fmrtb   1/1     Running   0          72m   10.244.1.9   192.168.18.5-hd1   <none>           <none>
nginx-645ccd8dc9-w75cd   1/1     Running   0          72m   10.244.1.8   192.168.18.5-hd1   <none>           <none>

  

因为是副本部署,所以当一个pod被删除,就会自动创建新的pod

可见,删除一个pod的下一刻,新的pod已经被创建,但还没准备好,也没有分配ip

# kubectl delete pod nginx-645ccd8dc9-fmrtb
pod "nginx-645ccd8dc9-fmrtb" deleted

# kubectl get pods -l app=nginx -o wide    
NAME                     READY   STATUS              RESTARTS   AGE     IP           NODE                          NOMINATED NODE   READINESS GATES
nginx-645ccd8dc9-pr8l7   0/1     ContainerCreating   0          5s      <none>       kibanaprod-192.168.18.5-hd1   <none>           <none>
nginx-645ccd8dc9-w75cd   1/1     Running             0          4h28m   10.244.1.8   kibanaprod-192.168.18.5-hd1   <none>           <none>

  

过几秒钟就已经分配好,这个新的pod ip和原来的是不一样的。

# kubectl get pods -l app=nginx -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP            NODE                          NOMINATED NODE   READINESS GATES
nginx-645ccd8dc9-pr8l7   1/1     Running   0          112s    10.244.1.13   kibanaprod-192.168.18.5-hd1   <none>           <none>
nginx-645ccd8dc9-w75cd   1/1     Running   0          4h30m   10.244.1.8    kibanaprod-192.168.18.5-hd1   <none>           <none>

  

curl pod ip可以直接访问

从k8s master上traceroute发现是直接通过flannel网络达到位于另一个node上的pod。

# curl 10.244.1.9

working. Further configuration is required.</p>

[root@masterpub-10.0.0.80-hd1 18:03 /data/k8s/nginx]
# traceroute 10.244.1.9
traceroute to 10.244.1.9 (10.244.1.9), 30 hops max, 60 byte packets
 1  10.244.1.0 (10.244.1.0)  1.321 ms *  1.225 ms
 2  10.244.1.9 (10.244.1.9)  1.290 ms  1.248 ms  1.212 ms

  

service expose

--port svc端口

--target-port 容器端口

--type 类型  ClusterIP, NodePort, LoadBalancer, or ExternalName. Default is 'ClusterIP'

一个svc,将一个deployment对接起来

10.99.188.113这个地址是动态生成的,它只有在集群内部才能访问到。但master上无法访问,在node上使用curl就能访问。

# kubectl get deployment       
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   2/2     2            2           4h42m

# kubectl expose deployment nginx --name nginx-svc --port=80 --target-port=80
service/nginx-svc exposed

# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   29d
nginx-svc    ClusterIP   10.99.188.113   <none>        80/TCP    92s

  

查看svc的详细信息

可以看到它的名称,名称空间,标签选择器,类型,ip,endpoint

# kubectl describe svc nginx-svc
Name:              nginx-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP:                10.99.188.113
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.15:80,10.244.1.16:80
Session Affinity:  None
Events:            <none>

动态修改svc的type,改成NodePort,这样外网就能访问到

# kubectl edit svc nginx-svc

  

# kubectl get svc           
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        29d
nginx-svc    NodePort    10.99.188.113   <none>        80:31621/TCP   59m

  

这时外网访问k8s集群中任意一个node:port,都能连接到svc。

可以做一个外部的内网SLB,绑定一个外网,把所有node接入。

scale扩容

如果两个副本不够用,可以动态扩展

# kubectl scale --replicas=4 deployment nginx
deployment.apps/nginx scaled

# kubectl get pods -l app=nginx
NAME                     READY   STATUS    RESTARTS   AGE
nginx-645ccd8dc9-9xkwd   1/1     Running   0          16m
nginx-645ccd8dc9-nfthl   1/1     Running   0          16m
nginx-645ccd8dc9-q6nlt   1/1     Running   0          82s
nginx-645ccd8dc9-x4gbk   1/1     Running   0          82s

也可以缩容,指定副本数,又只剩下2个了

# kubectl scale --replicas=2 deployment nginx 
deployment.apps/nginx scaled
[root@masterpub-10.0.0.80-hd1 22:14 ~]

NAME                     READY   STATUS    RESTARTS   AGE
nginx-645ccd8dc9-9xkwd   1/1     Running   0          18m
nginx-645ccd8dc9-nfthl   1/1     Running   0          18m

  

更新/回滚deployment

查看目前的deployment,image是nginx

# kubectl describe deployment nginx

  Containers:
   nginx:
    Image:        nginx
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>

查看目前deployment相关的pods,都在运行

# kubectl get pods -l app=nginx
NAME                     READY   STATUS    RESTARTS   AGE
nginx-645ccd8dc9-fj2kk   1/1     Running   0          3m25s
nginx-645ccd8dc9-jfspl   1/1     Running   0          3m25s
nginx-645ccd8dc9-l9686   1/1     Running   0          21m
nginx-645ccd8dc9-nb8zl   1/1     Running   0          21m

  

更新image

# kubectl set image deployment/nginx nginx=nginx:1.9.1
deployment.apps/nginx image updated

  

# kubectl describe deployment nginx

  Containers:
   nginx:
    Image:        nginx:1.9.1
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>

  

第一次查看时,pods正在滚动替换,创建新的pod,销毁旧的。

第二次查看时,已全部替换

# kubectl get pods -l app=nginx
NAME                     READY   STATUS              RESTARTS   AGE
nginx-544b8d8974-78k8d   0/1     ContainerCreating   0          5s
nginx-544b8d8974-g28kz   1/1     Running             0          24s
nginx-544b8d8974-tlx4h   0/1     ContainerCreating   0          24s
nginx-645ccd8dc9-jfspl   1/1     Running             0          4m19s
nginx-645ccd8dc9-l9686   0/1     Terminating         0          22m
nginx-645ccd8dc9-nb8zl   1/1     Running             0          22m

# kubectl get pods -l app=nginx
NAME                     READY   STATUS    RESTARTS   AGE
nginx-544b8d8974-78k8d   1/1     Running   0          2m54s
nginx-544b8d8974-g28kz   1/1     Running   0          3m13s
nginx-544b8d8974-gnhqk   1/1     Running   0          2m33s
nginx-544b8d8974-tlx4h   1/1     Running   0          3m13s

  

回滚刚才的更新

# kubectl rollout undo deployment/nginx  
deployment.apps/nginx rolled back

# kubectl rollout status deployment/nginx
Waiting for deployment "nginx" rollout to finish: 2 out of 4 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 2 out of 4 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 2 out of 4 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 3 out of 4 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 3 out of 4 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 3 out of 4 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 3 out of 4 new replicas have been updated...
Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx" rollout to finish: 3 of 4 updated replicas are available...
deployment "nginx" successfully rolled out

  

coredns

service提供一个ip,但外界访问需要一个域名,这个解析的工作就是coredns来完成

# kubectl get pods -o wide -n kube-system|grep dns
coredns-7ff77c879f-6wkt6                          1/1     Running   0          29d   10.244.0.2     masterpub-10.0.0.80-hd1       <none>           <none>
coredns-7ff77c879f-m2crn                          1/1     Running   0          29d   10.244.0.3     masterpub-10.0.0.80-hd1       <none>           <none>
# 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   29d

  

部署一个交互式的busybox测试,查看它的dns解析,可见就是coredns的svc地址

# kubectl run client-test --image=busybox -it --restart=Never
If you don't see a command prompt, try pressing enter.
/ # cat /etc/resolv.conf 
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

  

访问svc的域名,可见,已经成功解析

/ # wget nginx-svc
Connecting to nginx-svc (10.99.188.113:80)

  

尝试删除deployment里的两个pod,然后再测试在pod客户端里访问域名

前面10s左右无法通信,后面就有了,说明deployment里的pod已经重新创建,svc不管后面怎么变化,都通信正常

/ # wget -O - -q http://nginx-svc
wget: can't connect to remote host (10.99.188.113): Connection refused
/ # wget -O - -q http://nginx-svc
wget: can't connect to remote host (10.99.188.113): Connection refused
/ # wget -O - -q http://nginx-svc
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

  

service文件部署

改成NodePort,就是映射到node的port上。这里没有写nodeport的值,就是随机,范围是30000多。

文件中使用标签选择器,就是将app:nginx的pod纳入service。

# cat nginx_deployment_svc
apiVersion: v1
kind: Service
metadata:
  name: nginxservice
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
    - name: https
      protocol: TCP
      port: 443
      targetPort: 443

  

查看service的信息,看到type,集群ip,端口映射。

查看这个service的endpoint信息,可见将两个pod已经纳入

# kubectl get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
nginxservice   NodePort    10.96.65.135    <none>        80:30205/TCP,443:32418/TCP   64m

# kubectl get ep nginxservice
NAME           ENDPOINTS                                                 AGE
nginxservice   10.244.1.8:443,10.244.1.9:443,10.244.1.8:80 + 1 more...   66m

  

访问顺序

这时外网就从node ip访问nginx service

先到node ip,再到cluster ip,再到pod ip

从仓库中拉取镜像部署

创建一个namespace

#cat namespace.yaml

apiVersion: v1

kind: Namespace

metadata:

name: redis

kubectl apply -f namespace.yaml

kubectl get namespace

创建一个configmap

redis.conf

kubectl create configmap redis-conf --from-file=redis.conf -n redis

kubectl get configmap -n redis