CKA认证模块②-K8S企业运维和落地实战

CKA认证模块②-K8S企业运维和落地实战

Pod高级实战-Pod生命周期-启动钩子,停止钩子

Pod生命周期完整流程介绍

容器钩子; 容器探测; Pod重启策略; Pod的终止过程;

Init容器;

初始化容器最佳实践

初始化容器与主容器区别是?

init容器没有readinessProbe…

[root@k8s-master01 pod-2]# cat init.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
  containers:
  - name: myapp-container
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
[root@k8s-master01 pod-2]# kubectl apply -f init.yaml 
pod/myapp-pod created
[root@k8s-master01 ~]# kubectl get pods -w
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Init:0/2   0          0s
myapp-pod   0/1     Init:0/2   0          0s
myapp-pod   0/1     Init:0/2   0          1s
# 初始化容器创建不出来,主容器就出不来

[root@k8s-master01 pod-2]# kubectl delete -f init.yaml 
pod "myapp-pod" deleted
[root@k8s-master01 pod-2]# cat init.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', "sleep 2"]
  - name: init-mydb
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
  containers:
  - name: myapp-container
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
[root@k8s-master01 pod-2]# kubectl apply -f init.yaml 
pod/myapp-pod created
[root@k8s-master01 ~]# kubectl get pods -w
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Init:0/2   0          0s
myapp-pod   0/1     Init:0/2   0          0s
myapp-pod   0/1     Init:0/2   0          2s
myapp-pod   0/1     Init:1/2   0          4s
myapp-pod   0/1     Init:1/2   0          5s

[root@k8s-master01 pod-2]# kubectl delete -f init.yaml 
pod "myapp-pod" deleted
[root@k8s-master01 pod-2]# cat init.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', "sleep 2"]
  - name: init-mydb
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', "sleep 2"]
  containers:
  - name: myapp-container
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo 主容器正常启动! && sleep 3600']
[root@k8s-master01 pod-2]# kubectl apply -f init.yaml 
pod/myapp-pod created
[root@k8s-master01 ~]# kubectl get pods -w
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Init:0/2   0          0s
myapp-pod   0/1     Init:0/2   0          1s
myapp-pod   0/1     Init:0/2   0          1s
myapp-pod   0/1     Init:1/2   0          4s
myapp-pod   0/1     Init:1/2   0          5s
myapp-pod   0/1     PodInitializing   0          7s
myapp-pod   1/1     Running           0          8s
# init容器必须全能执行成功,主容器才能运行起来
初始化容器生产应用

主容器运行nginx服务,初始化容器用来给主容器生成index.html文件

[root@k8s-master01 pod-2]# cat init-1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: initnginx
spec:
  initContainers:
  - name: install
    image: docker.io/library/busybox:1.28
    imagePullPolicy: IfNotPresent
    command:
    - wget
    - "-O"
    - "/work-dir/index.html"
    - "https://www.baidu.com"
    volumeMounts:
    - name: workdir
      mountPath: /work-dir
  containers:
  - name: nginx
    image: docker.io/xianchao/nginx:v1
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    volumeMounts:
    - name: workdir
      mountPath: /usr/share/nginx/html
  volumes:
  - name: workdir
    emptyDir: {}

[root@k8s-master01 pod-2]# kubectl apply -f init-1.yaml 
pod/initnginx created
[root@k8s-master01 pod-2]# kubectl get pods -owide
NAME        READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
initnginx   1/1     Running   0          14s   10.244.85.195   k8s-node01   <none>           <none>
[root@k8s-master01 pod-2]# curl 10.244.85.195
...
[root@k8s-master01 pod-2]# kubectl exec -it initnginx -c nginx -- /bin/bash
root@initnginx:/# ls /usr/share/nginx/html/           
index.html
Pod生命周期-容器钩子

postStartpreStop

[root@k8s-master01 pod-2]# kubectl explain pod.spec.containers.lifecycle
# 查看帮助及写法
[root@k8s-master01 pod-2]# kubectl delete -f init-1.yaml 
pod "initnginx" deleted
[root@k8s-master01 pod-2]# cat pre-start.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: life-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: docker.io/xianchao/nginx:v1
    imagePullPolicy: IfNotPresent
    lifecycle:
      postStart:
         exec:
           command: ["/bin/sh", "-c","echo 'lifecycle hookshandler' > /usr/share/nginx/html/test.html"]
      preStop:
         exec:
           command:
           - "/bin/sh"
           - "-c"
           - "nginx -s stop"

[root@k8s-master01 pod-2]# kubectl apply -f pre-start.yaml 
pod/life-demo created
[root@k8s-master01 pod-2]# kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
life-demo   1/1     Running   0          25s
[root@k8s-master01 pod-2]# kubectl exec -it life-demo -- /bin/bash
root@life-demo:/# cd /usr/share/nginx/html/
root@life-demo:/usr/share/nginx/html# cat test.html 
lifecycle hookshandler
# 测试成功

[root@k8s-master01 pod-2]# kubectl delete -f pre-start.yaml 
pod "life-demo" deleted
# 清除环境

总结:

pod在整个生命周期中有非常多的用户行为:

  1. 初始化容器完成初始化

  2. 主容器启动后可以做启动后钩子(postStart)

  3. 主容器结束前可以做结束前钩子(preStop)

  4. 在主容器运行中可以做一些健康检测,如:startupProbe, livenessProbe, readnessProbe

零故障升级之Pod健康检测

启动探测startupProbe

小测试

[root@k8s-master01 ~]# mkdir pod-4
[root@k8s-master01 ~]# cd pod-4
[root@k8s-master01 pod-4]# cat check.yaml
apiVersion: v1
kind: Pod
metadata:
  name: check
  namespace: default
  labels:
    app: check
spec:
  containers:
  - name: check
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command:
    - /bin/sh
    - -c
    - sleep 10; exit
# 使容器运行10秒后就退出
[root@k8s-master01 pod-4]# kubectl apply -f check.yaml
pod/check created
[root@k8s-master01 pod-2]# kubectl get pods -w
NAME    READY   STATUS    RESTARTS   AGE
check   0/1     Pending   0          0s
check   0/1     Pending   0          0s
check   0/1     ContainerCreating   0          0s
check   0/1     ContainerCreating   0          1s
check   1/1     Running             0          2s
check   0/1     Completed           0          12s
check   1/1     Running             1 (2s ago)   13s
check   0/1     Completed           1 (12s ago)   23s
# 检查pod状态

[root@k8s-master01 pod-4]# kubectl delete -f check.yaml 
pod "check" deleted
# 清除环境
提问: k8s提供了三种探针实现容器探测,哪三种? 作用分别是什么?

Pod探针相关属性

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.startupProbe.exec
# 查看帮助
[root@k8s-master01 pod-4]# cat startup-exec.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: startupprobe
spec:
  containers:
  - name: startup
    image: xianchao/tomcat-8.5-jre8:v1
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    startupProbe:
     exec:
       command:
       - "/bin/sh"
       - "-c"
       - "ps aux | grep tomcat"
     initialDelaySeconds: 20 #容器启动后多久开始探测
     periodSeconds: 20 #执行探测的时间间隔
     timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
     successThreshold: 1 #成功多少次才算成功
     failureThreshold: 3 #失败多少次才算失败
[root@k8s-master01 pod-4]# kubectl apply -f startup-exec.yaml 
pod/startupprobe created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME           READY   STATUS    RESTARTS   AGE
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     Running             0          1s
startupprobe   0/1     Running             0          15s
startupprobe   0/1     Running             0          20s
startupprobe   1/1     Running             0          20s
# 测试探测时间

[root@k8s-master01 pod-4]# kubectl delete -f startup-exec.yaml 
pod "startupprobe" deleted
# 删除环境

[root@k8s-master01 pod-4]# cat startup-exec.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: startupprobe
spec:
  containers:
  - name: startup
    image: xianchao/tomcat-8.5-jre8:v1
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    startupProbe:
     exec:
       command:
       - "/bin/sh"
       - "-c"
       - "aa ps aux | grep tomcat1" # 修改为一条不存在的命令测试
     initialDelaySeconds: 20 #容器启动后多久开始探测
     periodSeconds: 20 #执行探测的时间间隔
     timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
     successThreshold: 1 #成功多少次才算成功
     failureThreshold: 3 #失败多少次才算失败
[root@k8s-master01 pod-4]# kubectl apply -f startup-exec.yaml 
pod/startupprobe created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME           READY   STATUS    RESTARTS   AGE
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     Running             0          2s
startupprobe   0/1     Running             1 (0s ago)   81s
startupprobe   0/1     Running             2 (1s ago)   2m41s
startupprobe   0/1     Running             3 (1s ago)   4m1s
# 测试探测

[root@k8s-master01 pod-4]# kubectl delete -f startup-exec.yaml 
pod "startupprobe" deleted
# 删除环境
提问: 第一次探测失败多久会重启?

根据如上测试回答,为什么是60秒?为什么是80秒

tcpSocket模式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.startupProbe.tcpSocket
# 查看帮助
[root@k8s-master01 pod-4]# cat startup-tcpsocket.yaml
apiVersion: v1
kind: Pod
metadata:
  name: startupprobe
spec:
  containers:
  - name: startup
    image: xianchao/tomcat-8.5-jre8:v1
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    startupProbe:
     tcpSocket:
       port: 8080
     initialDelaySeconds: 20 #容器启动后多久开始探测
     periodSeconds: 20 #执行探测的时间间隔
     timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
     successThreshold: 1 #成功多少次才算成功
     failureThreshold: 3 #失败多少次才算失败
[root@k8s-master01 pod-4]# kubectl apply -f startup-tcpsocket.yaml 
pod/startupprobe created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME           READY   STATUS    RESTARTS   AGE
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     ContainerCreating   0          1s
startupprobe   0/1     Running             0          1s
startupprobe   0/1     Running             0          40s
startupprobe   1/1     Running             0          40s
# 测试tcpSocket

[root@k8s-master01 pod-4]# kubectl delete -f startup-tcpsocket.yaml 
pod "startupprobe" deleted
# 清除环境

httpGet模式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.startupProbe.httpGet.
# 查看帮助
[root@k8s-master01 pod-4]# cat startup-httpget.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: startupprobe
spec:
  containers:
  - name: startup
    image: xianchao/tomcat-8.5-jre8:v1
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    startupProbe:
      httpGet:
        path: /
        port: 8080
      initialDelaySeconds: 20 #容器启动后多久开始探测
      periodSeconds: 20 #执行探测的时间间隔
      timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
      successThreshold: 1 #成功多少次才算成功
      failureThreshold: 3 #失败多少次才算失败

[root@k8s-master01 pod-4]# kubectl apply -f startup-httpget.yaml 
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME           READY   STATUS    RESTARTS   AGE
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     Running             0          1s
startupprobe   0/1     Running             0          41s
startupprobe   1/1     Running             0          41s
# 测试httpGet

[root@k8s-master01 pod-4]# kubectl delete -f startup-httpget.yaml 
pod "startupprobe" deleted
# 清除环境

启动探测间隔说明: 不同探针可能有误差,影响不大

存活性探测livenessProbe

exec方式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.livenessProbe.exec.
# 查看帮助
[root@k8s-master01 pod-4]# cat liveness-exec.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec
  labels:
    app: liveness
spec:
  containers:
  - name: liveness
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    args:                       #创建测试探针探测的文件
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      initialDelaySeconds: 10   #延迟检测时间
      periodSeconds: 5          #检测时间间隔
      exec:
        command:
        - cat
        - /tmp/healthy
[root@k8s-master01 pod-4]# kubectl apply -f liveness-exec.yaml
pod/liveness-exec created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME            READY   STATUS    RESTARTS   AGE
liveness-exec   0/1     Pending   0          0s
liveness-exec   0/1     Pending   0          0s
liveness-exec   0/1     ContainerCreating   0          0s
liveness-exec   0/1     ContainerCreating   0          1s
liveness-exec   1/1     Running             0          2s
liveness-exec   1/1     Running             1 (1s ago)   76s
liveness-exec   1/1     Running             2 (0s ago)   2m31s
# 测试exec

[root@k8s-master01 pod-4]# kubectl delete -f liveness-exec.yaml
pod "liveness-exec" deleted
# 清除环境

httpGet方式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.livenessProbe.httpGet.
# 查看帮助
[root@k8s-master01 pod-4]# ctr -n k8s.io images import springboot.tar.gz 
[root@k8s-node01 images]# ctr -n k8s.io images import springboot.tar.gz 
[root@k8s-node02 images]# ctr -n k8s.io images import springboot.tar.gz
# 节点导入镜像
[root@k8s-master01 pod-4]# cat liveness-http.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: liveness-http
  labels:
    test: liveness
spec:
  containers:
  - name: liveness
    image: mydlqclub/springboot-helloworld:0.0.1
    imagePullPolicy: IfNotPresent
    livenessProbe:
      initialDelaySeconds: 20   #延迟加载时间
      periodSeconds: 5          #重试时间间隔
      timeoutSeconds: 10        #超时时间设置
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/health
[root@k8s-master01 pod-4]# kubectl apply -f liveness-http.yaml 
pod/liveness-http created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME            READY   STATUS    RESTARTS   AGE
liveness-http   0/1     Pending   0          0s
liveness-http   0/1     Pending   0          0s
liveness-http   0/1     ContainerCreating   0          0s
liveness-http   0/1     ContainerCreating   0          0s
liveness-http   1/1     Running             0          1s
[root@k8s-master01 pod-4]# kubectl get pods -owide
NAME            READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
liveness-http   1/1     Running   0          5m24s   10.244.58.209   k8s-node02   <none>           <none>
[root@k8s-master01 pod-4]# curl 10.244.58.209:8081/actuator/health
{"status":"UP"}
# 测试httpGet

[root@k8s-master01 pod-4]# kubectl delete -f liveness-http.yaml 
pod "liveness-http" deleted
# 清除环境

tcpSocket方式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.livenessProbe.tcpSocket.
# 查看帮助
[root@k8s-master01 pod-4]# cat liveness-tcp.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcp
  labels:
    app: liveness
spec:
  containers:
  - name: liveness
    image: docker.io/xianchao/nginx:v1
    imagePullPolicy: IfNotPresent
    livenessProbe:
      initialDelaySeconds: 15
      periodSeconds: 20
      tcpSocket:
        port: 80
[root@k8s-master01 pod-4]# kubectl apply -f liveness-tcp.yaml 
pod/liveness-tcp created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME           READY   STATUS    RESTARTS   AGE
liveness-tcp   0/1     Pending   0          0s
liveness-tcp   0/1     Pending   0          0s
liveness-tcp   0/1     ContainerCreating   0          0s
liveness-tcp   0/1     ContainerCreating   0          0s
liveness-tcp   1/1     Running             0          2s
# 测试tcpSocket

[root@k8s-master01 pod-4]# kubectl delete -f liveness-tcp.yaml 
pod "liveness-tcp" deleted
# 清除环境
就绪性探测readinessProbe

exec方式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.readinessProbe.
# 查看帮助
[root@k8s-master01 pod-4]# cat readiness-exec.yaml 
apiVersion: v1
kind: Service
metadata:
  name: springboot
  labels:
    app: springboot
spec:
  type: NodePort
  ports:
  - name: server
    port: 8080
    targetPort: 8080
    nodePort: 31180
  - name: management
    port: 8081
    targetPort: 8081
    nodePort: 31181
  selector:
    app: springboot
---
apiVersion: v1
kind: Pod
metadata:
  name: springboot
  labels:
    app: springboot
spec:
  containers:
  - name: springboot
    image: mydlqclub/springboot-helloworld:0.0.1
    imagePullPolicy: IfNotPresent
    ports:
    - name: server
      containerPort: 8080
    - name: management
      containerPort: 8081
    readinessProbe:
      initialDelaySeconds: 20   
      periodSeconds: 5          
      timeoutSeconds: 10   
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/health
[root@k8s-master01 pod-4]# kubectl apply -f readiness-exec.yaml 
service/springboot created
pod/springboot created
[root@k8s-master01 pod-4]# kubectl get pods -l app=springboot -w
NAME         READY   STATUS    RESTARTS   AGE
springboot   0/1     Pending   0          1s
springboot   0/1     Pending   0          3s
springboot   0/1     ContainerCreating   0          3s
springboot   0/1     ContainerCreating   0          6s
springboot   0/1     Running             0          9s
springboot   1/1     Running             0          49s
[root@k8s-master01 pod-4]# kubectl get svc -w
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   4d2h
springboot   NodePort    10.106.29.40   <none>        8080:31180/TCP,8081:31181/TCP   0s
# 只有pod就绪了,才能被service关联到,所以就绪探测很重要

注意: 存活探测和就绪探测不存在先后,而是平行

启动,就绪,存活探测混合使用
[root@k8s-master01 pod-4]# cat start-read-live.yaml 
apiVersion: v1
kind: Service
metadata:
  name: springboot-live
  labels:
    app: springboot
spec:
  type: NodePort
  ports:
  - name: server
    port: 8080
    targetPort: 8080
    nodePort: 31180
  - name: management
    port: 8081
    targetPort: 8081
    nodePort: 31181
  selector:
    app: springboot
---
apiVersion: v1
kind: Pod
metadata:
  name: springboot-live
  labels:
    app: springboot
spec:
  containers:
  - name: springboot
    image: mydlqclub/springboot-helloworld:0.0.1
    imagePullPolicy: IfNotPresent
    ports:
    - name: server
      containerPort: 8080
    - name: management
      containerPort: 8081
    readinessProbe:
      initialDelaySeconds: 20   
      periodSeconds: 5          
      timeoutSeconds: 10   
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/health
    livenessProbe:
      initialDelaySeconds: 20
      periodSeconds: 5
      timeoutSeconds: 10
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/health
    startupProbe:
      initialDelaySeconds: 20
      periodSeconds: 5
      timeoutSeconds: 10
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/health
[root@k8s-master01 pod-4]# kubectl apply -f start-read-live.yaml 
service/springboot-live created
pod/springboot-live created

[root@k8s-master01 pod-4]# kubectl exec -it springboot-live -- kill 1
# 等容器起来再执行
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME              READY   STATUS    RESTARTS   AGE
springboot-live   0/1     Pending   0          0s
springboot-live   0/1     Pending   0          0s
springboot-live   0/1     ContainerCreating   0          0s
springboot-live   0/1     ContainerCreating   0          1s
springboot-live   0/1     Running             0          4s
springboot-live   0/1     Running             0          26s
# 注意这里为什么会有两个,因为我们设置了存活和就绪探测
springboot-live   1/1     Running             0          26s
springboot-live   0/1     Error               0          61s
springboot-live   0/1     Running             1 (3s ago)   63s
springboot-live   0/1     Running             1 (26s ago)   86s
# 同上
springboot-live   1/1     Running             1 (26s ago)   86s

[root@k8s-master01 pod-4]# kubectl delete -f start-read-live.yaml 
service "springboot-live" deleted
pod "springboot-live" deleted
# 清除环境

三种探测大致可以理解为:

startupProbe用于pod启动探测

livenessProbe用于容器启动探测

readinessProbe用于容器内服务状态探测

K8S控制器ReplicaSet入门到企业实战应用

ReplicaSet资源-YAML文件编写技巧
[root@k8s-master01 rs]# kubectl explain replicaset.
# 查看帮助

ctr -n k8s.io images import frontend.tar.gz
ctr -n k8s.io images import myapp-blue-v1.tar.gz
ctr -n k8s.io images import myapp-blue-v2.tar.gz
ctr -n k8s.io images import myapp-v2.tar.gz
# 导入镜像

[root@k8s-master01 rs]# cat replicaset.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  namespace: default
  labels:
    app: guestbook
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier1: frontend1
  template:
    metadata:
      labels:
        tier1: frontend1
    spec:
      containers:
      - name: php-redis
        image: docker.io/yecc/gcr.io-google_samples-gb-frontend:v3
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        startupProbe:
          initialDelaySeconds: 20
          periodSeconds: 5
          timeoutSeconds: 10
          httpGet: 
            scheme: HTTP
            port: 80
            path: /
        livenessProbe:
          initialDelaySeconds: 20
          periodSeconds: 5
          timeoutSeconds: 10
          httpGet: 
            scheme: HTTP
            port: 80
            path: /
        readinessProbe:
          initialDelaySeconds: 20
          periodSeconds: 5
          timeoutSeconds: 10
          httpGet: 
            scheme: HTTP
            port: 80
            path: /
[root@k8s-master01 rs]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend created
[root@k8s-master01 rs]# kubectl get pod -w
NAME             READY   STATUS    RESTARTS   AGE
frontend-2h7l7   0/1     Pending   0          0s
frontend-2h7l7   0/1     Pending   0          0s
frontend-2xmw6   0/1     Pending   0          0s
frontend-6cb5q   0/1     Pending   0          0s
frontend-2xmw6   0/1     Pending   0          0s
frontend-6cb5q   0/1     Pending   0          0s
frontend-2xmw6   0/1     ContainerCreating   0          0s
frontend-2h7l7   0/1     ContainerCreating   0          0s
frontend-6cb5q   0/1     ContainerCreating   0          0s
frontend-2h7l7   0/1     ContainerCreating   0          1s
frontend-2xmw6   0/1     ContainerCreating   0          1s
frontend-6cb5q   0/1     ContainerCreating   0          1s
frontend-2xmw6   0/1     Running             0          2s
frontend-6cb5q   0/1     Running             0          2s
frontend-2h7l7   0/1     Running             0          2s
frontend-2h7l7   0/1     Running             0          21s
frontend-2h7l7   1/1     Running             0          21s
frontend-6cb5q   0/1     Running             0          21s
frontend-6cb5q   1/1     Running             0          21s
frontend-2xmw6   0/1     Running             0          22s
frontend-2xmw6   1/1     Running             0          22s
[root@k8s-master01 rs]# kubectl get rs
NAME       DESIRED   CURRENT   READY   AGE
frontend   3         3         0       10s
# 创建ReplicaSet

[root@k8s-master01 rs]# kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
frontend-2h7l7   1/1     Running   0          57s
frontend-2xmw6   1/1     Running   0          57s
frontend-6cb5q   1/1     Running   0          57s
[root@k8s-master01 rs]# kubectl delete pod frontend-2h7l7
pod "frontend-2h7l7" deleted
[root@k8s-master01 rs]# kubectl get pod -w
NAME             READY   STATUS    RESTARTS   AGE
frontend-2h7l7   1/1     Running   0          75s
frontend-2xmw6   1/1     Running   0          75s
frontend-6cb5q   1/1     Running   0          75s
frontend-2h7l7   1/1     Terminating   0          79s
frontend-g6prf   0/1     Pending       0          1s
frontend-g6prf   0/1     Pending       0          1s
frontend-g6prf   0/1     ContainerCreating   0          1s
frontend-2h7l7   1/1     Terminating         0          80s
frontend-g6prf   0/1     ContainerCreating   0          2s
frontend-2h7l7   0/1     Terminating         0          81s
frontend-2h7l7   0/1     Terminating         0          81s
frontend-2h7l7   0/1     Terminating         0          81s
frontend-g6prf   0/1     Running             0          3s
frontend-g6prf   0/1     Running             0          27s
frontend-g6prf   1/1     Running             0          27s
# 测试删除ReplicaSet管理的pod,如果少了replicaSet会重新创建一个pod
ReplicaSet实现pod扩缩容和更新
[root@k8s-master01 rs]# cat replicaset.yaml |grep replicas:
  replicas: 4
[root@k8s-master01 rs]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend configured
[root@k8s-master01 rs]# kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
frontend-2xmw6   1/1     Running   0          31m
frontend-69p98   1/1     Running   0          52s
frontend-6cb5q   1/1     Running   0          31m
frontend-g6prf   1/1     Running   0          30m
# 直接修改yaml文件然后应用实现pod扩容

[root@k8s-master01 rs]# cat replicaset.yaml |grep replicas:
  replicas: 2
[root@k8s-master01 rs]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend configured
[root@k8s-master01 rs]# kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
frontend-2xmw6   1/1     Running   0          33m
frontend-g6prf   1/1     Running   0          31m
# 实现pod缩容

[root@k8s-master01 rs]# cat replicaset.yaml |grep image:
        image: docker.io/ikubernetes/myapp:v2
[root@k8s-master01 rs]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend configured
[root@k8s-master01 rs]# kubectl get pods -owide
NAME             READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
frontend-2xmw6   1/1     Running   0          35m   10.244.85.205   k8s-node01   <none>           <none>
frontend-g6prf   1/1     Running   0          33m   10.244.85.206   k8s-node01   <none>           <none>
[root@k8s-master01 rs]# curl 10.244.85.205 |head -n3
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     100   921  100   921    0     0   527k      0 --:--:-- --:--:-- --:--:--  899k
<html ng-app="redis">
  <head>
    <title>Guestbook</title>
# ReplicaSet没有更新容器使用镜像,仍然是之前的内容
[root@k8s-master01 rs]# kubectl delete pod frontend-2xmw6
pod "frontend-2xmw6" deleted
[root@k8s-master01 rs]# kubectl delete pod frontend-g6prf
pod "frontend-g6prf" deleted
[root@k8s-master01 rs]# kubectl get pods -owide
NAME             READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
frontend-8cdmn   1/1     Running   0          2m13s   10.244.58.221   k8s-node02   <none>           <none>
frontend-mk6ln   0/1     Running   0          25s     10.244.85.207   k8s-node01   <none>           <none>
[root@k8s-master01 rs]# curl 10.244.58.221
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
# ReplicaSet无法自动完成更新,必须手动删除pod

[root@k8s-master01 rs]# kubectl delete -f replicaset.yaml 
replicaset.apps "frontend" deleted
# 清除环境

总结:

生产环境如果升级,可以删除一个pod,观察一段时间之后没问题再删除另一个pod,但是这样需要人工干预多次;实际生产环境一般采用蓝绿发布,原来有一个rs1,再创建一个rs2(控制器),通过修改service标签,修改service可以匹配到rs2的控制器,这样才是蓝绿发布,这个也需要我们精心的部署规划,我们有一个控制器就是建立在rs之上完成的,叫做Deployment

K8S控制器Deployment入门到企业实战应用

Deployment资源基本介绍

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意: rollingUpdate更新策略计算方式
[root@k8s-master01 ~]# kubectl explain deploy.spec.strategy.rollingUpdate.
# 查看帮助

最多可用小数直接进一位

最多不可用小数直接舍去保留整数

replicas: 5

​ maxSurge: 25% 5*25%=1.25 -> 5+2=7

​ maxUnanvilable: 25% 5*25%=1.25 -> 5-1=4

Deployment资源-YAML文件编写技巧
[root@k8s-master01 ~]# mkdir deployment
[root@k8s-master01 ~]# cd deployment/
[root@k8s-master01 deployment]# kubectl explain deploy.
# 查看帮助

ctr -n k8s.io images import myapp-blue-v1.tar.gz 
ctr -n k8s.io images import myapp-blue-v2.tar.gz
# 导入镜像

[root@k8s-master01 deployment]# cat deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v1
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      version: v1
  template:
    metadata:
      labels:
        app: myapp
        version: v1
    spec:
      containers:
      - name: myapp
        image: janakiramm/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        startupProbe:
          initialDelaySeconds: 20
          periodSeconds: 5
          timeoutSeconds: 10
          httpGet:
            port: 80
            path: /
            scheme: HTTP
        livenessProbe:
          initialDelaySeconds: 20
          periodSeconds: 5
          timeoutSeconds: 10
          httpGet:
            port: 80
            path: /
            scheme: HTTP
        readinessProbe:
          initialDelaySeconds: 20
          periodSeconds: 5
          timeoutSeconds: 10
          httpGet:
            port: 80
            path: /
            scheme: HTTP
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 created
[root@k8s-master01 deployment]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-58bdffcdd7-bn79v   1/1     Running   0          77s
myapp-v1-58bdffcdd7-cqz99   1/1     Running   0          77s
[root@k8s-master01 deployment]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   2         2         2       79s
[root@k8s-master01 deployment]# kubectl get deployment
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
myapp-v1   2/2     2            2           86s
# 创建deployment
Deployment实现pod扩缩容
[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep replicas:
  replicas: 3
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
[root@k8s-master01 deployment]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-58bdffcdd7-b64k7   1/1     Running   0          32s
myapp-v1-58bdffcdd7-bn79v   1/1     Running   0          3m3s
myapp-v1-58bdffcdd7-cqz99   1/1     Running   0          3m3s
[root@k8s-master01 deployment]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   3         3         3       3m9s
[root@k8s-master01 deployment]# kubectl get deploy
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
myapp-v1   3/3     3            3           3m11s
# 通过修改yaml文件中的replicas实现pod扩容

[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep replicas:
  replicas: 2
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
[root@k8s-master01 deployment]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-58bdffcdd7-bn79v   1/1     Running   0          4m15s
myapp-v1-58bdffcdd7-cqz99   1/1     Running   0          4m15s
[root@k8s-master01 deployment]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   2         2         2       4m17s
[root@k8s-master01 deployment]# kubectl get deployment
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
myapp-v1   2/2     2            2           4m20s
# 实现pod缩容,会随机删除pod
Deployment实现Pod滚动更新
[root@k8s-master01 deployment]# kubectl explain deploy.spec.strategy.
# 查看帮助
[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep replicas:
  replicas: 3
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
# 先将pod副本数调为3并应用

[root@k8s-master01 deployment]# kubectl describe deployments.apps myapp-v1 |grep -i strategy
StrategyType:           RollingUpdate
RollingUpdateStrategy:  25% max unavailable, 25% max surge
# 可以看到默认策略是滚动更新
# 默认最多不可用是25%,最多可用也为25%

replicas: 3
maxSurge: 25% -> 3+1=4
maxUnavailabel: 25% -> 3-0=3

[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep image:
        image: janakiramm/myapp:v2
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
# 修改使用镜像使滚动更新
[root@k8s-master01 deployment]# kubectl get pods -w
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-58bdffcdd7-bn79v   1/1     Running   0          29m
myapp-v1-58bdffcdd7-cqz99   1/1     Running   0          29m
myapp-v1-58bdffcdd7-vxbjk   1/1     Running   0          5m4s
####################
myapp-v1-744bfb8886-8xrzt   0/1     Pending   0          0s
myapp-v1-744bfb8886-8xrzt   0/1     Pending   0          0s
myapp-v1-744bfb8886-8xrzt   0/1     ContainerCreating   0          0s
myapp-v1-744bfb8886-8xrzt   0/1     ContainerCreating   0          0s
myapp-v1-744bfb8886-8xrzt   0/1     Running             0          1s
myapp-v1-744bfb8886-8xrzt   0/1     Running             0          25s
myapp-v1-744bfb8886-8xrzt   1/1     Running             0          25s
myapp-v1-58bdffcdd7-vxbjk   1/1     Terminating         0          6m4s
myapp-v1-744bfb8886-92vvt   0/1     Pending             0          0s
myapp-v1-744bfb8886-92vvt   0/1     Pending             0          0s
myapp-v1-744bfb8886-92vvt   0/1     ContainerCreating   0          0s
myapp-v1-58bdffcdd7-vxbjk   1/1     Terminating         0          6m5s
...
[root@k8s-master01 deployment]# kubectl get rs -w
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   3         3         3       29m
###################
myapp-v1-744bfb8886   1         0         0       0s
myapp-v1-744bfb8886   1         0         0       0s
myapp-v1-744bfb8886   1         1         0       0s
myapp-v1-744bfb8886   1         1         1       25s
myapp-v1-58bdffcdd7   2         3         3       30m
...
[root@k8s-master01 deployment]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   0         0         0       31m
myapp-v1-744bfb8886   3         3         3       83s
# 滚动更新完成
Deployment回滚
[root@k8s-master01 deployment]# kubectl rollout history deployment myapp-v1 
deployment.apps/myapp-v1 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

# 查看deployment滚动更新历史
[root@k8s-master01 deployment]# kubectl rollout undo deployment/myapp-v1 --to-revision=1
deployment.apps/myapp-v1 rolled back
[root@k8s-master01 deployment]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-58bdffcdd7-2tgr2   1/1     Running   0          2m2s
myapp-v1-58bdffcdd7-bk6w7   1/1     Running   0          101s
myapp-v1-58bdffcdd7-lrjhp   1/1     Running   0          81s
[root@k8s-master01 deployment]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   3         3         3       35m
myapp-v1-744bfb8886   0         0         0       5m57s
# 实现回滚
自定义Deployment更新策略
[root@k8s-master01 deployment]# kubectl explain deploy.spec.strategy.
# 查看帮助
[root@k8s-master01 deployment]# cat deploy-demo.yaml |head -n15
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v1
  namespace: default
spec:
  strategy: 
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: v1
[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep image:
        image: janakiramm/myapp:v2
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
[root@k8s-master01 deployment]# kubectl get pods -w
...
# 测试rollingUpdate

当前pod数量为3,限定后更新过程中pod可用数量为2-4.

测试Recreate

生产环境一定别用,因为全部重建需要时间,生产业务是不能down掉的

[root@k8s-master01 deployment]# cat deploy-demo.yaml |head -n15
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v1
  namespace: default
spec:
  strategy: 
    type: Recreate
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: v1
  template:
    metadata:
[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep image:
        image: janakiramm/myapp:v1
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
[root@k8s-master01 deployment]# kubectl get pods -w
...

[root@k8s-master01 deployment]# kubectl delete -f deploy-demo.yaml 
deployment.apps "myapp-v1" deleted
# 清除环境
蓝绿部署基本介绍

蓝绿部署中,一共有两套系统:一套是正在提供服务系统,标记为“绿色”;另一套是准备发布的系统,标记为“蓝色”。两套系统都是功能完善的、正在运行的系统,只是系统版本和对外服务情况不同。(蓝绿都可代表新旧系统,理解意思即可,不必在乎颜色)

开发新版本,要用新版本替换线上的旧版本,在线上的系统之外,搭建了一个使用新版本代码的全新系统。 这时候,一共有两套系统在运行,正在对外提供服务的老系统是绿色系统,新部署的系统是蓝色系统。

优点:

1、更新过程无需停机,风险较少

2、回滚方便,只需要更改路由或者切换DNS服务器,效率较高

缺点:

1、成本较高,需要部署两套环境。如果新版本中基础服务出现问题,会瞬间影响全网用户;如果新版本有问题也会影响全网用户。

2、需要部署两套机器,费用开销大

3、在非隔离的机器(Docker、VM)上操作时,可能会导致蓝绿环境被摧毁风险

4、负载均衡器/反向代理/路由/DNS处理不当,将导致流量没有切换过来情况出现

基于k8s实现蓝绿部署

Kubernetes不支持内置的蓝绿部署.目前最好的方式市创建新的deployment,然后更新应用程序的service以指向新的deployment部署的应用

ctr -n k8s.io images import myapp-lan.tar.gz
ctr -n k8s.io images import myapp-lv.tar.gz
# 节点导入镜像

[root@k8s-master01 deployment]# kubectl create ns blue-green
namespace/blue-green created
[root@k8s-master01 deployment]# cat lan.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v1
  namespace: blue-green
spec:
  replicas: 3
  selector:
   matchLabels:
    app: myapp
    version: v1
  template:
   metadata:
    labels:
     app: myapp
     version: v1
   spec:
    containers:
    - name: myapp
      image: janakiramm/myapp:v1
      imagePullPolicy: IfNotPresent
      ports:
      - containerPort: 80

[root@k8s-master01 deployment]# kubectl apply -f lan.yaml 
deployment.apps/myapp-v1 created
# 部署正在提供服务的系统
[root@k8s-master01 deployment]# cat service_lanlv.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-lan-lv
  namespace: blue-green
  labels:
    app: myapp
spec:
  type: NodePort
  ports:
  - port: 80
    nodePort: 30062
    name: http
  selector:
    app: myapp
    version: v1

[root@k8s-master01 deployment]# kubectl apply -f service_lanlv.yaml 
service/myapp-lan-lv created
[root@k8s-master01 deployment]# kubectl describe svc myapp-lan-lv -n blue-green |grep -i endpoints:
Endpoints:                10.244.58.236:80,10.244.58.237:80,10.244.85.217:80
# 编写service的yaml文件对外提供服务

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

网页访问正常

[root@k8s-master01 deployment]# cat lv.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v2
  namespace: blue-green
spec:
  replicas: 3
  selector:
   matchLabels:
    app: myapp
    version: v2
  template:
   metadata:
    labels:
     app: myapp
     version: v2
   spec:
    containers:
    - name: myapp
      image: janakiramm/myapp:v2
      imagePullPolicy: IfNotPresent
      ports:
      - containerPort: 80

[root@k8s-master01 deployment]# kubectl apply -f lv.yaml 
deployment.apps/myapp-v2 created
# 部署第二套系统,也就是准备发布的新系统
[root@k8s-master01 deployment]# kubectl get pods -n blue-green
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-7b55fffbb5-2vpt7   1/1     Running   0          3m11s
myapp-v1-7b55fffbb5-gfnnt   1/1     Running   0          3m11s
myapp-v1-7b55fffbb5-xpk2f   1/1     Running   0          3m11s
myapp-v2-5779dc88f-55566    1/1     Running   0          16s
myapp-v2-5779dc88f-cjnrp    1/1     Running   0          16s
myapp-v2-5779dc88f-sz2m9    1/1     Running   0          16s
[root@k8s-master01 deployment]# kubectl get pods --show-labels -n blue-green
NAME                        READY   STATUS    RESTARTS   AGE     LABELS
myapp-v1-7b55fffbb5-2vpt7   1/1     Running   0          5m25s   app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v1-7b55fffbb5-gfnnt   1/1     Running   0          5m25s   app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v1-7b55fffbb5-xpk2f   1/1     Running   0          5m25s   app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v2-5779dc88f-55566    1/1     Running   0          2m30s   app=myapp,pod-template-hash=5779dc88f,version=v2
myapp-v2-5779dc88f-cjnrp    1/1     Running   0          2m30s   app=myapp,pod-template-hash=5779dc88f,version=v2
myapp-v2-5779dc88f-sz2m9    1/1     Running   0          2m30s   app=myapp,pod-template-hash=5779dc88f,version=v2
[root@k8s-master01 deployment]# cat service_lanlv.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-lan-lv
  namespace: blue-green
  labels:
    app: myapp
spec:
  type: NodePort
  ports:
  - port: 80
    nodePort: 30062
    name: http
  selector:
    app: myapp
    version: v2
# 只需修改service的yaml文件的匹配标签即可,这里我们修改了version为v2
[root@k8s-master01 deployment]# kubectl apply -f service_lanlv.yaml 
service/myapp-lan-lv configured
[root@k8s-master01 deployment]# kubectl describe svc myapp-lan-lv -n blue-green |grep -i endpoints:
Endpoints:                10.244.58.238:80,10.244.85.218:80,10.244.85.219:80
[root@k8s-master01 deployment]# kubectl get pods --show-labels -n blue-green -owide
NAME                        READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES   LABELS
myapp-v1-7b55fffbb5-2vpt7   1/1     Running   0          5m40s   10.244.58.237   k8s-node02   <none>           <none>            app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v1-7b55fffbb5-gfnnt   1/1     Running   0          5m40s   10.244.85.217   k8s-node01   <none>           <none>            app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v1-7b55fffbb5-xpk2f   1/1     Running   0          5m40s   10.244.58.236   k8s-node02   <none>           <none>            app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v2-5779dc88f-55566    1/1     Running   0          2m45s   10.244.58.238   k8s-node02   <none>           <none>            app=myapp,pod-template-hash=5779dc88f,version=v2
myapp-v2-5779dc88f-cjnrp    1/1     Running   0          2m45s   10.244.85.218   k8s-node01   <none>           <none>            app=myapp,pod-template-hash=5779dc88f,version=v2
myapp-v2-5779dc88f-sz2m9    1/1     Running   0          2m45s   10.244.85.219   k8s-node01   <none>           <none>            app=myapp,pod-template-hash=5779dc88f,version=v2
# 已经切换为新的系统

[root@k8s-master01 deployment]# kubectl delete -f lv.yaml 
deployment.apps "myapp-v2" deleted
[root@k8s-master01 deployment]# kubectl delete -f lan.yaml 
deployment.apps "myapp-v1" deleted
[root@k8s-master01 deployment]# kubectl delete -f service_lanlv.yaml 
service "myapp-lan-lv" deleted
# 清除环境

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

网页访问正常

基于k8s实现金丝雀发布
金丝雀发布简介

**金丝雀发布的由来:**17 世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感。空气中哪怕有极其微量的瓦斯,金丝雀也会停止歌唱;当瓦斯含量超过一定限度时,虽然人类毫无察觉,金丝雀却早已毒发身亡。当时在采矿设备相对简陋的条件下,工人们每次下井都会带上一只金丝雀作为瓦斯检测指标,以便在危险状况下紧急撤离。

**金丝雀发布(又称灰度发布、灰度更新):**金丝雀发布一般先发1台,或者一个小比例,例如2%的服务器,主要做流量验证用,也称为金丝雀 (Canary) 测试 (国内常称灰度测试)。

简单的金丝雀测试一般通过手工测试验证,复杂的金丝雀测试需要比较完善的监控基础设施配合,通过监控指标反馈,观察金丝雀的健康状况,作为后续发布或回退的依据。 如果金丝测试通过,则把剩余的V1版本全部升级为V2版本。如果金丝雀测试失败,则直接回退金丝雀,发布失败。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

[root@k8s-master01 deployment]# kubectl apply -f lan.yaml 
deployment.apps/myapp-v1 created
[root@k8s-master01 deployment]# kubectl set image deployment myapp-v1 myapp=docker.io/xianchao/nginx:v1  -n blue-green && kubectl rollout pause deployment myapp-v1 -n blue-green
deployment.apps/myapp-v1 image updated
deployment.apps/myapp-v1 paused
[root@k8s-master01 deployment]# kubectl get pods -n blue-green -w
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-7b55fffbb5-46cqg   1/1     Running   0          5s
myapp-v1-7b55fffbb5-8mh8k   1/1     Running   0          5s
myapp-v1-7b55fffbb5-fnb8c   1/1     Running   0          5s
#######################

myapp-v1-644d75999-2dlks    0/1     Pending   0          0s
myapp-v1-644d75999-2dlks    0/1     Pending   0          0s
myapp-v1-644d75999-2dlks    0/1     ContainerCreating   0          0s
myapp-v1-644d75999-2dlks    0/1     ContainerCreating   0          0s
myapp-v1-644d75999-2dlks    1/1     Running             0          1s
# 新起一个pod做金丝雀发布,其余三个pod为暂停状态,也就是暂不更新,还是跑着旧业务

[root@k8s-master01 deployment]# kubectl rollout resume deployment myapp-v1 -n blue-green
deployment.apps/myapp-v1 resumed
[root@k8s-master01 deployment]# kubectl get pods -n blue-green -w
...
[root@k8s-master01 deployment]# kubectl get rs -n blue-green
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-644d75999    3         3         3       2m25s
myapp-v1-7b55fffbb5   0         0         0       2m32s
# 如果没有问题,就全部更新,解除暂停状态

K8S四层代理Service入门到企业实战

Service四层代理基本介绍
提问: 为什么要有Service?

Service概述

较新的版本使用的是coredns),service的名称解析是依赖于dns附件的,因此在部署完k8s之后需要再部署dns附件,kubernetes要想给客户端提供网络功能,需要依赖第三方的网络插件(flannel,calico等)。

每个K8s节点上都有一个组件叫做kube-proxy,kube-proxy这个组件将始终监视着apiserver中有关service资源的变动信息,需要跟master之上的apiserver交互,随时连接到apiserver上获取任何一个与service资源相关的资源变动状态,这种是通过kubernetes中固有的一种请求方法watch(监视)来实现的,一旦有service资源的内容发生变动(如创建,删除),kube-proxy都会将它转化成当前节点之上的能够实现service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是iptables,也可能是ipvs,取决于service的实现方式。

Service工作原理

k8s在创建Service时,会根据标签选择器selector(lable selector)来查找Pod,据此创建与Service同名的endpoint对象,当Pod 地址发生变化时,endpoint也会随之发生变化,service接收前端client请求的时候,就会通过endpoint,找到转发到哪个Pod进行访问的地址。(至于转发到哪个节点的Pod,由负载均衡kube-proxy决定)

K8S集群中有三类IP地址

  1. Node Network(节点网络)
  2. Pod Network(Pod网络)
  3. Cluster Network(集群地址,也称为service network)
Service代理-ClusterIP类型
[root@k8s-master01 ~]# kubectl explain service.spec.
# 查看帮助

[root@k8s-node01 images]# ctr -n k8s.io images import nginx.tar.gz
[root@k8s-node02 images]# ctr -n k8s.io images import nginx.tar.gz
# 工作节点导入镜像

[root@k8s-master01 ~]# mkdir service
[root@k8s-master01 ~]# cd service/
[root@k8s-master01 service]# cat pod_test.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80  #pod中的容器需要暴露的端口
        startupProbe:
           periodSeconds: 5
           initialDelaySeconds: 60
           # 初始检测时间设置长一点,方便测试
           timeoutSeconds: 10
           httpGet:
             scheme: HTTP
             port: 80
             path: /
        livenessProbe:
           periodSeconds: 5
           initialDelaySeconds: 60
           timeoutSeconds: 10
           httpGet:
             scheme: HTTP
             port: 80
             path: /
        readinessProbe:
           periodSeconds: 5
           initialDelaySeconds: 60
           timeoutSeconds: 10
           httpGet:
             scheme: HTTP
             port: 80
             path: /
[root@k8s-master01 service]# kubectl apply -f pod_test.yaml 
deployment.apps/my-nginx created
# 创建deployment生成pod
[root@k8s-master01 service]# kubectl get pods --show-labels
NAME                        READY   STATUS    RESTARTS   AGE   LABELS
my-nginx-7468bcb55b-b7vnl   0/1     Running   0          23s   pod-template-hash=7468bcb55b,run=my-nginx
my-nginx-7468bcb55b-zzpw2   0/1     Running   0          23s   pod-template-hash=7468bcb55b,run=my-nginx
# 查看pod标签
[root@k8s-master01 service]# cat service_test.yaml 
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  type: ClusterIP
  ports:
  - port: 80
    # service的端口,暴露给k8s集群内部服务访问
    protocol: TCP
    targetPort: 80
    # pod容器中定义的端口
  selector:
    run: my-nginx
    # 选择拥有run=my-nginx标签的pod
[root@k8s-master01 service]# kubectl apply -f service_test.yaml 
service/my-nginx created
# 创建service
[root@k8s-master01 service]# kubectl get svc -l run=my-nginx
NAME       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
my-nginx   ClusterIP   10.98.163.90   <none>        80/TCP    50s
[root@k8s-master01 service]# curl 10.98.163.90
...
# 测试service,ClusterIP类型只有集群内部可访问
[root@k8s-master01 service]# kubectl describe svc my-nginx |grep -i endpoints:
Endpoints:         10.244.58.246:80,10.244.85.224:80

[root@k8s-master01 service]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-7468bcb55b-b7vnl   1/1     Running   0          5m53s
my-nginx-7468bcb55b-zzpw2   1/1     Running   0          5m53s
[root@k8s-master01 service]# kubectl delete pod my-nginx-7468bcb55b-b7vnl 
pod "my-nginx-7468bcb55b-b7vnl" deleted
[root@k8s-master01 service]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-7468bcb55b-8vz67   0/1     Running   0          49s
my-nginx-7468bcb55b-zzpw2   1/1     Running   0          6m46s
[root@k8s-master01 service]# kubectl describe svc my-nginx |grep -i endpoints:
Endpoints:         10.244.85.224:80
# 在pod的服务没有就绪前不会代理
[root@k8s-master01 service]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-7468bcb55b-8vz67   1/1     Running   0          63s
my-nginx-7468bcb55b-zzpw2   1/1     Running   0          7m
[root@k8s-master01 service]# kubectl get pods -owide
NAME                        READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
my-nginx-7468bcb55b-8vz67   1/1     Running   0          74s     10.244.58.247   k8s-node02   <none>           <none>
my-nginx-7468bcb55b-zzpw2   1/1     Running   0          7m11s   10.244.85.224   k8s-node01   <none>           <none>
[root@k8s-master01 service]# kubectl describe svc my-nginx |grep -i endpoints:
Endpoints:         10.244.58.247:80,10.244.85.224:80
# 所以就绪探测很重要,不然可能造成service代理了但是服务没起来的情况

[root@k8s-master01 service]# kubectl delete -f pod_test.yaml 
deployment.apps "my-nginx" deleted
[root@k8s-master01 service]# kubectl delete -f service_test.yaml 
service "my-nginx" deleted
# 清除环境

以这个service为例,它的全称为my-nginx.default.svc.cluster.local

也就是: 服务名.命名空间.域名后缀

这个全称只能在关联的pod里访问,集群节点也是无法访问的

Service代理-NodePort类型
[root@k8s-master01 service]# cat pod_nodeport.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx-nodeport
spec:
  selector:
    matchLabels:
      run: my-nginx-nodeport
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx-nodeport
    spec:
      containers:
      - name: my-nginx-nodeport-container
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

[root@k8s-master01 service]# kubectl apply -f pod_nodeport.yaml 
deployment.apps/my-nginx-nodeport created
[root@k8s-master01 service]# cat service_nodeport.yaml 
apiVersion: v1
kind: Service
metadata:
  name: my-nginx-nodeport
  labels:
    run: my-nginx-nodeport
spec:
  type: NodePort
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30380
  selector:
    run: my-nginx-nodeport

[root@k8s-master01 service]# kubectl apply -f service_nodeport.yaml 
service/my-nginx-nodeport created
[root@k8s-master01 service]# kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
my-nginx-nodeport-85c4df8944-g8s85   1/1     Running   0          19s
my-nginx-nodeport-85c4df8944-k6b9f   1/1     Running   0          19s
[root@k8s-master01 service]# kubectl get svc
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes          ClusterIP   10.96.0.1        <none>        443/TCP        8d
my-nginx-nodeport   NodePort    10.110.139.100   <none>        80:30380/TCP   13s
# 创建pod和NodePort类型的service

[root@k8s-master01 service]# ss -lntup |grep 30380
# 查端口是查不到的
[root@k8s-master01 service]# ipvsadm -Ln |head -n10
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.17.0.1:30380 rr
  -> 10.244.58.249:80             Masq    1      0          0         
  -> 10.244.85.227:80             Masq    1      0          0         
TCP  192.168.1.181:30380 rr
  -> 10.244.58.249:80             Masq    1      1          0         
  -> 10.244.85.227:80             Masq    1      0          1 
# 查询防火墙规则

[root@k8s-master01 service]# kubectl delete -f pod_nodeport.yaml 
deployment.apps "my-nginx-nodeport" deleted
[root@k8s-master01 service]# kubectl delete -f service_nodeport.yaml 
service "my-nginx-nodeport" deleted
# 清除环境

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据转发流程:

客户端请求http://192.168.1.181:30380->docker0虚拟网卡:172.17.0.1:30380->10.244.121.36:80,10.244.102.86:80

Service代理-ExternalName类型

应用场景:跨名称空间访问

需求:default名称空间下的client 服务想要访问nginx-ns名称空间下的nginx-svc服务

[root@k8s-node01 images]# ctr -n k8s.io images import busybox.tar.gz
[root@k8s-node02 images]# ctr -n k8s.io images import busybox.tar.gz
# 工作节点导入镜像

[root@k8s-master01 service]# kubectl create ns nginx-ns
namespace/nginx-ns created
[root@k8s-master01 service]# cat server_nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: nginx-ns
spec: 
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
   metadata:
    labels:
      app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx
       imagePullPolicy: IfNotPresent

[root@k8s-master01 service]# kubectl apply -f server_nginx.yaml 
deployment.apps/nginx created
# 部署nginx-ns名称空间下的pod跑nginx服务
[root@k8s-master01 service]# cat nginx_svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  namespace: nginx-ns
spec:
  selector:
    app: nginx
  ports:
   - name: http
     protocol: TCP
     port: 80
     targetPort: 80
[root@k8s-master01 service]# kubectl apply -f nginx_svc.yaml 
service/nginx-svc created
# 部署nginx的service,类型为ClusterIP
[root@k8s-master01 service]# cat client.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: client
spec: 
  replicas: 1
  selector:
    matchLabels:
      app: busybox
  template:
   metadata:
    labels:
      app: busybox
   spec:
     containers:
     - name: busybox
       image: busybox
       imagePullPolicy: IfNotPresent
       command: ["/bin/sh","-c","sleep 36000"]

[root@k8s-master01 service]# kubectl apply -f client.yaml 
deployment.apps/client created
# 部署默认名称空间下的client
[root@k8s-master01 service]# cat client_svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: client-svc
spec:
  type: ExternalName
  externalName: nginx-svc.nginx-ns.svc.cluster.local
  ports:
  - name: http
    port: 80
    targetPort: 80

[root@k8s-master01 service]# kubectl apply -f client_svc.yaml 
service/client-svc created
# 创建ExternalName类型的service
[root@k8s-master01 service]# kubectl get svc
NAME         TYPE           CLUSTER-IP   EXTERNAL-IP                            PORT(S)   AGE
client-svc   ExternalName   <none>       nginx-svc.nginx-ns.svc.cluster.local   80/TCP    89s
kubernetes   ClusterIP      10.96.0.1    <none>                                 443/TCP   8d
[root@k8s-master01 service]# kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
client-798446484b-wrz86   1/1     Running   0          2m6s
[root@k8s-master01 service]# kubectl exec -it client-798446484b-wrz86 -- /bin/sh
/ # wget -q -O - client-svc
...
/ # wget -q -O - client-svc.default.svc.cluster.local
...
/ # wget -q -O - nginx-svc.nginx-ns.svc.cluster.local
...
# 上面三个请求结果一样

[root@k8s-master01 service]# kubectl delete -f client_svc.yaml 
service "client-svc" deleted
[root@k8s-master01 service]# kubectl delete -f client.yaml 
deployment.apps "client" deleted
[root@k8s-master01 service]# kubectl delete -f server_nginx.yaml 
deployment.apps "nginx" deleted
# 清除环境
Service代理-自定义Endpoints资源

k8s最佳实践:映射外部服务案例分享

场景1:k8s集群引用外部的mysql数据库

[root@k8s-node02 ~]# yum -y install mariadb-server
[root@k8s-node02 ~]# systemctl enable --now mariadb
[root@k8s-node02 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 5.5.68-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> quit
Bye
# 在node2安装节点外部服务mariadb-server做测试

[root@k8s-master01 service]# cat mysql_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql
  namespace: default
spec:
  type: ClusterIP
  ports:
  - port: 3306
[root@k8s-master01 service]# kubectl apply -f mysql_service.yaml 
service/mysql created
# 创建ClusterIP类型的service
[root@k8s-master01 service]# kubectl get svc |grep mysql
mysql        ClusterIP   10.106.232.15   <none>        3306/TCP   43s
[root@k8s-master01 service]# kubectl describe svc mysql |grep -i endpoints:
Endpoints:         <none>
# 可以看到Endpoints: 字段是空的,所以我们要去添加一个

[root@k8s-master01 service]# kubectl explain endpoints.
# 查看帮助
[root@k8s-master01 service]# cat mysql_endpoints.yaml
apiVersion: v1
kind: Endpoints
metadata:
  name: mysql
  # 注意这里要与service名字相同,不然找不到
  namespace: default
subsets:
- addresses: 
  - ip: 192.168.1.192
  ports:
  - port: 3306
[root@k8s-master01 service]# kubectl apply -f mysql_endpoints.yaml 
endpoints/mysql created
# 创建mysql的endpoints
[root@k8s-master01 service]# kubectl describe svc mysql |grep -i endpoints:
Endpoints:         192.168.1.192:3306
# 可以看到已经匹配上

[root@k8s-master01 service]# kubectl delete -f mysql_endpoints.yaml 
endpoints "mysql" deleted
[root@k8s-master01 service]# kubectl delete -f mysql_service.yaml 
service "mysql" deleted
[root@k8s-node02 ~]# yum -y remove mariadb-server
# 清除环境

这样集群内部就可以访问service到外部的服务了

coredns组件详解

CoreDNS 其实就是一个 DNS 服务,而 DNS 作为一种常见的服务发现手段,所以很多开源项目以及工程师都会使用 CoreDNS 为集群提供服务发现的功能,Kubernetes 就在集群中使用 CoreDNS 解决服务发现的问题。 作为一个加入 CNCF(Cloud Native Computing Foundation)的服务, CoreDNS 的实现非常简单。

验证coredns

[root@k8s-node01 ~]# ctr -n k8s.io images import dig.tar.gz
[root@k8s-node02 ~]# ctr -n k8s.io images import dig.tar.gz
# 工作节点导入镜像

[root@k8s-master01 service]# cat dig.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: dig
  namespace: default
spec:
  containers:
  - name: dig
    image:  xianchao/dig:latest
    imagePullPolicy: IfnotPresent
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always

[root@k8s-master01 service]# kubectl apply -f dig.yaml 
pod/dig created
[root@k8s-master01 service]# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
dig    1/1     Running   0          114s
# 创建测试pod
[root@k8s-master01 service]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   8d
[root@k8s-master01 service]# kubectl exec -it dig -- /bin/bash
bash-4.3# nslookup kubernetes
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	kubernetes.default.svc.cluster.local
Address: 10.96.0.1
# 测试集群内部
bash-4.3# nslookup baidu.com
Server:		10.96.0.10
Address:	10.96.0.10#53

Non-authoritative answer:
Name:	baidu.com
Address: 39.156.66.10
Name:	baidu.com
Address: 110.242.68.66
# 测试集群外部

bash-4.3# exit
exit
[root@k8s-master01 service]# kubectl delete -f dig.yaml 
pod "dig" deleted
[root@k8s-master01 service]# kubectl delete -f .
# 清除环境

ot@k8s-master01 service]# kubectl delete -f mysql_endpoints.yaml
endpoints “mysql” deleted
[root@k8s-master01 service]# kubectl delete -f mysql_service.yaml
service “mysql” deleted
[root@k8s-node02 ~]# yum -y remove mariadb-server

清除环境


这样集群内部就可以访问service到外部的服务了

#### coredns组件详解

**CoreDNS 其实就是一个 DNS 服务,而 DNS 作为一种常见的服务发现手段,所以很多开源项目以及工程师都会使用 CoreDNS 为集群提供服务发现的功能,Kubernetes 就在集群中使用 CoreDNS 解决服务发现的问题。 作为一个加入 CNCF(Cloud Native Computing Foundation)的服务**, **CoreDNS 的实现非常简单。**

验证coredns

```shell
[root@k8s-node01 ~]# ctr -n k8s.io images import dig.tar.gz
[root@k8s-node02 ~]# ctr -n k8s.io images import dig.tar.gz
# 工作节点导入镜像

[root@k8s-master01 service]# cat dig.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: dig
  namespace: default
spec:
  containers:
  - name: dig
    image:  xianchao/dig:latest
    imagePullPolicy: IfnotPresent
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always

[root@k8s-master01 service]# kubectl apply -f dig.yaml 
pod/dig created
[root@k8s-master01 service]# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
dig    1/1     Running   0          114s
# 创建测试pod
[root@k8s-master01 service]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   8d
[root@k8s-master01 service]# kubectl exec -it dig -- /bin/bash
bash-4.3# nslookup kubernetes
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	kubernetes.default.svc.cluster.local
Address: 10.96.0.1
# 测试集群内部
bash-4.3# nslookup baidu.com
Server:		10.96.0.10
Address:	10.96.0.10#53

Non-authoritative answer:
Name:	baidu.com
Address: 39.156.66.10
Name:	baidu.com
Address: 110.242.68.66
# 测试集群外部

bash-4.3# exit
exit
[root@k8s-master01 service]# kubectl delete -f dig.yaml 
pod "dig" deleted
[root@k8s-master01 service]# kubectl delete -f .
# 清除环境

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/132255.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python实现炒股自动化,个人账户无门槛量化交易的开始

本篇作为系列教程的引子&#xff0c;对股票量化程序化自动交易感兴趣的朋友可以关注我&#xff0c;现在只是个粗略计划&#xff0c;后续会根据需要重新调整&#xff0c;并陆续添加内容。 股票量化程序化自动交易接口 很多人在找股票个人账户实现程序化自动交易的接口&#xff0…

Java_继承和多态

文章目录 前言继承继承语法继承总结super指定访问父级子类构造方法super和this再谈初始化(执行顺序)protected 关键字继承方式final 关键字继承与组合 多态动态绑定与静态绑定多态实现条件重写 前言 适合复习看 继承 继承语法 修饰符 class 子类 extends 父类 { // ... }子类…

配置cuda和cudnn出现 libcudnn.so.8 is not a symbolic link问题

cuda版本为11.2 问题如图所示&#xff1a; 解决办法&#xff1a; sudo ln -sf /usr/local/cuda-11.2/targets/x86_64-linux/lib/libcudnn_adv_train.so.8.1.1 /usr/local/cuda-11.2/targets/x86_64-linux/lib/libcudnn_adv_train.so.8 sudo ln -sf /usr/local/cuda-11.2/targ…

Mac安装配置Tomcat,以及使用(详解)

目录 一、Tomcat下载&#xff1a; 1、左栏选择Tomcat版本 2、点击下载即可&#xff0c;任选其一 ​编辑3、下载好的文件夹放到用户名下即可&#xff08;之前已经下载过&#xff0c;这里以Tomcat 8.5.88为演示&#xff09;&#xff0c;这里提供8.5.88的安装包&#xff1a; 二…

毅速丨金属3D打印零件品质受哪些因素影响

金属3D打印的零件品质受到多个因素的影响&#xff0c;包括设备、材料、工艺、后处理等。不同厂商的品质差别大致由以下几个方面造成。 一、设备性能差异&#xff1a; 不同厂商的金属3D打印设备可能存在性能上的差异&#xff0c;包括激光功率、扫描速度、打印精度、稳定性等。这…

istio流量管理

流量管理 目录 文章目录 流量管理目录流量管理概述请求路由1.路由到版本1&#x1f6a9; 实战&#xff1a;路由到版本1-2023.11.11(测试成功) 2.基于用户身份的路由&#x1f6a9; 实战&#xff1a;基于用户身份的路由-2023.11.11(测试成功) 关于我最后 流量管理概述 上面我们了…

跨镜头目标融合__追踪之目标重识别研究(跨镜头目标追踪)

文章目录 标题&#xff1a;跨镜头目标融合&#xff1b;目标重识别&#xff1b;跨镜头目标追踪&#xff1b; 1 目的&#xff1a;2 实现方法/策略&#xff1a;2.1 目标类型位置匹配&#xff08;或考虑结合目标轨迹&#xff09;2.2 目标重识别2.3 目标类型位置匹配(轨迹)目标重识别…

LeetCode【701】二叉搜索数的插入操作

题目&#xff1a; 思路&#xff1a; https://zhuanlan.zhihu.com/p/272781596 代码&#xff1a; class Solution {public TreeNode insertIntoBST(TreeNode root, int val) {return process(root,val); }//递归public TreeNode process(TreeNode root,int val){//base ca…

Hls学习(一)

1&#xff1a;CPU、DSP、GPU都算软件可编程的硬件 2&#xff1a;dsp在递归方面有所减弱&#xff0c;在递归方面有所增强&#xff0c;比如递归啊等&#xff0c;GPU可以同时处理多个进程&#xff0c;对于大块数据&#xff0c;流处理比较适用 3&#xff1a;为了提高运算量处理更多…

可视化 | 3D文字球状标签云

文章目录 &#x1f4da;改编点&#x1f4da;final 改编自echarts 3d词云&#xff08;指向滑动、拖动、缩放、点击、自转 &#xff09; &#x1f4da;改编点 背景透明&#xff1a;background:rgb(0,0,0,0);不用链接&#xff0c;用span&#xff0c;重点span标class"star&q…

文心耀乌镇,“大模型之光”展现了什么?

“乌镇的小桥流水&#xff0c;能照见全球科技的风起云涌。” 多年以来&#xff0c;伴随着中国科技的腾飞&#xff0c;以及世界互联网大会乌镇峰会的连续成功举办&#xff0c;这句话已经成为全球科技产业的共识。乌镇是科技与互联网的风向标、晴雨表&#xff0c;也是无数新故事开…

【ATTCK】MITRE Caldera 简介

一、什么是Caldera caldera是一个基于MITRE ATT&CK™构建的网络安全框架。其目标是创建一种工具&#xff0c;通过提供自动化安全评估来增强网络从业者的能力&#xff0c;从而节省用户的时间、金钱和精力。为此&#xff0c;需要几个关键组件才能使 Caldera 成为行业领先的平…

外接式网络隔离变压器/网络隔离滤波器/网口变压器/脉冲变压器/网络隔离变压器模块

Hqst华强盛&#xff08;石门盈盛&#xff09;电子导读&#xff1a;外接式网络隔离变压器/网络隔离滤波器/网口变压器/脉冲变压器/网络隔离变压器模块&#xff0c;后统称网络隔离变压器&#xff0c;它是一种安装在电路外部的隔离变压器&#xff0c;主要用于隔离网络中的干扰信号…

巨好用又实用的18款3dMax插件!

3dMax是一款功能强大的 3D 软件&#xff0c;具有建模、动画、粒子动力学等许多强大功能。但并不是每个人都能有效地利用max的每一个功能&#xff0c;例如&#xff0c;很多人发现3dmax粒子流太难使用&#xff0c;3ds max蒙皮工具也是如此。 这让我们一些专业的开发公司或个人和…

跨域:利用iframe实现跨域DOM互访的四种方式

注&#xff1a;跨域的知识点详见&#xff1a;跨域相关知识点 目录 实验验证环境配置&#xff1a; 1、利用document.domain降域 方法1&#xff1a; 方法2&#xff1a; 2、利用location.hash 3、利用window.name 4、利用postMessage(最推荐) 使用postmessage实现跨域访问…

视频剪辑助手:轻松实现视频随机分割并提取音频保存

随着社交媒体和视频平台的日益普及&#xff0c;视频制作和分享已成为人们日常生活的一部分。无论是分享个人生活&#xff0c;还是展示才艺&#xff0c;或是推广产品&#xff0c;视频都是一个非常有效的工具。但是&#xff0c;视频制作往往涉及到大量的视频剪辑工作&#xff0c;…

卡码网语言基础课 | 11. 句子缩写

目录 一、 字符串大小的比较 二、 ASCII码值 三、 基本框架代码 四、 解题思路 4.1 首字母问题 4.2 判定小写字母 4.3 小写字母转换为大写字母 五、空格判断 六、 代码模块化 6.1 满足的条件 6.2 代码完善 七、 题目解答 7.1 原始代码 7.2 改进代码 八、 拓展与…

Redis五种数据类型及命令操作(一)

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 知足知不足 有为有不为 为与不为皆为可为&#x1f335; &#x1f349;本篇简介:&#x1f349; 本篇记录Redis五种数据类型及命令操作&#xff0c;如…

[BJDCTF2020]Easy MD5 1

题目环境&#xff1a; 尝试了SQL注入、命令执行等都不行 点击提交并burp进行抓包Repeater进行重放这里看到了内置的SQL语句select * from admin where passwordmd5($pass,true) 发现传进去的值会进行md5加密 这里看了大佬们的解释 ffifdyop绕过&#xff0c;绕过原理是&#xff…

计算机网络期末复习-Part3

1、rdt1.0&#xff0c;rdt2.0&#xff0c;rdt3.0的底层信道模型 RDT 1.0: 完全可靠的底层信道&#xff0c;没有比特差错&#xff0c;也没有分组丢失。 RDT 2.0: 具有比特差错的底层信道&#xff0c;有比特差错&#xff0c;但没有分组丢失。 RDT 3.0: 具有差错和丢包的底层信道…