K8s有很多技术概念,同时对应很多API对象,最重要的也是最基础的是微服务Pod。Pod是在K8s集群中运行部署应用或服务的最小单元,它是可以支持多容器的。Pod的设计理念是支持多个容器在一个Pod中共享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。Pod对多容器的支持是K8s最基础的设计理念。比如你运行一个操作系统发行版的软件仓库,一个Nginx容器用来发布软件,另一个容器专门用来从源仓库做同步,这两个容器的镜像不太可能是一个团队开发的,但是他们一块儿工作才能提供一个微服务;这种情况下,不同的团队各自开发构建自己的容器镜像,在部署的时候组合成一个微服务对外提供服务。这就是K8S中的POD。

 

1、Pod

kubernetes中,最基础单元就是Pod。Pod主要用来管理容器,通常Pod中包含的是一个调用链的服务。例如Nginx 和 Django
1.1、Pod的生命周期

 

创建两个容器 但是只能启动一个 一个deployment中两个容器_Pod

 

 

[root@k8s-master-01 k8s]# vim pod.yaml
kind: Pod
apiVersion: v1
metadata:
  name: testv1
spec:
  containers:
    - name: nginx
      image: nginx
      
# 部署
[root@k8s-master-01 k8s]# kubectl apply -f pod.yaml 
pod/testv1 created

# 查看
[root@k8s-master-01 k8s]# kubectl get pods 
NAME     READY   STATUS    RESTARTS   AGE
testv1   1/1     Running   0          52s
Pod名称  启动数量  运行状态   重启次数   启动时间
1.2、Pod的重启策略(restartPolicy)

https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/

[root@k8s-master-01 k8s]# kubectl explain pod.spec #这个路径下的 restartPolicy
Pod 的 spec 中包含一个 restartPolicy 字段,其可能取值包括 Always、OnFailure 和 Never。默认值是 Always。

restartPolicy 适用于 Pod 中的所有容器。restartPolicy 仅针对同一节点上 kubelet 的容器重启动作。当 Pod 中的容器退出时,kubelet 会按指数回退 方式计算重启的延迟(10s、20s、40s、...),其最长延迟为 5 分钟。 一旦某容器执行了 10 分钟并且没有出现问题,kubelet 对该容器的重启回退计时器执行 重置操作

当Pod出现了问题时,Pod怎么解决。
Always      :无论什么情况下退出,都重启
OnFailure   :只有当非正常情况下退出时,才会重启
Never       :无论什么情况下退出,都不重启
1.3、Pod中容器的拉取策略(imagePullPolicy)

https://kubernetes.io/docs/concepts/containers/images#updating-images

[root@k8s-master-01 k8s]# kubectl explain pod.spec.containers

容器的 imagePullPolicy 和镜像的标签会影响 kubelet 尝试拉取(下载)指定的镜像。
IfNotPresent    : 当本地没有该镜像时,下载
Always          :无论本地有没有该镜像,都去远程下载
Never           :无论本地有没有该镜像,都不去远程下载
kind: Pod
apiVersion: v1
metadata:
  name: testv1
spec:
  restartPolicy: OnFailure
  containers:
    - name: nginx
      image: nginx
      imagePullPolicy: IfNotPresent

# 删除Pod
[root@k8s-master-01 k8s]# kubectl delete -f pod.yaml 
# 部署Pod
[root@k8s-master-01 k8s]# kubectl apply -f pod.yaml 
pod/testv1 created
1.4、静态Pod和动态Pod之间的区别
静态Pod:没有控制器
动态Pod:有控制器
1.5、Pod的回调钩子
1.5.1、启动回调

[root@k8s-master-01 k8s]# kubectl explain pod.spec.containers.lifecycle

当Pod中所有的容器创建完成之后,立即调用的命令。

执行失败:如果启动回调钩子执行失败,容器无法进入正常启动状态。

exec        : 执行命令

[root@k8s-master-01 k8s]# >pod.yaml
[root@k8s-master-01 k8s]# vim pod.yaml

kind: Pod #资源的类型
apiVersion: v1 #版本
metadata: #属性
name: testv1 #pod的名字
spec: #详细
restartPolicy: OnFailure
containers: #容器(可申明多个容器)
- name: nginx #- 列表资源,说明有多个
image: nginx:1.18
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command:
- "/bin/sh"
- "-c"
- "echo 'Hello World!' > /root/1.txt"

[root@k8s-master-01 k8s]# kubectl apply -f pod.yaml
[root@k8s-master-01 k8s]# kubectl exec -it testv1 -- bash
root@testv1:/# cd
root@testv1:~# pwd
/root
root@testv1:~# ls
1.txt
root@testv1:~# cat 1.txt
Hello World!


httpGet     : 通过HTTP协议访问

kind: Pod
apiVersion: v1
metadata:
  name: testv1
spec:
  restartPolicy: OnFailure
  containers:
    - name: nginx
      image: nginx:1.18
      imagePullPolicy: IfNotPresent
      lifecycle:
        postStart:
          httpGet:
            port: 80
            path: /
            host: www.baidu.com    #域名
[root@k8s-master-01 k8s]# kubectl describe pod testv1


tcpSocket   : 通过Ping命令,探测端口
kind: Pod
apiVersion: v1
metadata:
  name: testv1
spec:
  restartPolicy: OnFailure
  containers:
    - name: nginx
      image: nginx:1.18
      imagePullPolicy: IfNotPresent
      lifecycle:
        postStart:
          tcpSocket:
            port: 80
            host: 106.13.81.75
1.5.2、就绪性检测(readinessProbe)
检测容器是否正常运行。

执行失败:如果就绪性检测执行失败,Pod会立即驱离出负载均衡。

exec        : 执行命令
httpGet     : 通过HTTP协议访问
          readinessProbe:
            httpGet:
              port: 80
              path: /index

tcpSocket   : 通过Ping命令,探测端口

service
1.5.3、存活性检测(livenessProbe)
检测容器是否正常启动。

执行失败:如果存活性检测执行失败,Pod会按照一定时间周期不断重启,直至Pod正常启动。

exec        : 执行命令
kind: Deployment
apiVersion: apps/v1
metadata:
  name: test-deployment
spec:
  selector:
    matchLabels:
      app: test-deployment
  template:
    metadata:
      labels:
        app: test-deployment
    spec:
      containers:
        - name: nginx
          image: nginx
          livenessProbe:
            exec:
              command:
                - "bin/sh"
                - "-c"
                - "cat /etc/hostss"
        # hostss不存在,所以存活性检测失败,pod会不断重启


httpGet     : 通过HTTP协议访问
          livenessProbe:
            httpGet:
              port: 8080
              path: /
              由于nginx是80端口,8080端口不存在,所有会不断重启

tcpSocket   : 通过Ping命令,探测端口
          livenessProbe:
            tcpSocket:
              port: 80
控制器

[root@k8s-master-01 k8s]# kubectl describe pod test-deployment-7b5cc5f5b9-vd8tr
1.5.4、结束回调
当Pod收到了销毁指令时,立即执行。

执行失败:如果结束回调执行失败,容器依然会终止。

exec        : 执行命令
httpGet     : 通过HTTP协议访问
tcpSocket   : 通过Ping命令,探测端口

kind: Pod
apiVersion: v1
metadata:
  name: testv1
spec:
  restartPolicy: OnFailure
  containers:
    - name: nginx
      image: nginx:1.18
      imagePullPolicy: IfNotPresent
      lifecycle:
        preStop:
          exec:
            command:
              - "/bin/sh"
              - "-c"
              - "echo 'HelloWorld' > /root/2.txt"
              
     创建了pod,当删除pod时,会创建2.txt

2、Deployment无状态控制器

k8s中所有的控制器都是用来管理Pod的。Deployment支持滚动更新、版本升级等功能。

2.1、Deployment案例
kind: Deployment
apiVersion: apps/v1
metadata:
  name: test-deployment
spec:
  selector:   # 选择Pod
    matchLabels:
      app: test-deployment
  template:   # 定义创建Pod的模板
    metadata:
      labels:
        app: test-deployment
    spec:
      containers:
        - name: nginx
          image: nginx

[root@k8s-master-01 k8s]# kubectl apply -f deployment.yaml 
#创建的资源
[root@k8s-master-01 k8s]# kubectl get deployments.apps 
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
test-deployment   1/1     1            1           99s
名字           启动Pod数量  理想状态     当前状态    时间
[root@k8s-master-01 k8s]# kubectl get pods 
NAME                             READY   STATUS    RESTARTS   AGE
test-deployment-574644b7-f27b9   1/1     Running   0          45s
2.2、Deployment动态扩容
[root@k8s-master-01 k8s]# kubectl scale deployment test-deployment --replicas=10
                                                控制器名称         指定副本数
2.3、Deployment的滚动更新
[root@k8s-master-01 k8s]# kubectl set image deployment/test-deployment nginx=nginx:1.18
deployment.apps/test-deployment image updated
[root@k8s-master-01 k8s]# kubectl get pods
2.4、Deployment回滚
# 查看一下部署历史
[root@k8s-master-01 k8s]# kubectl rollout history deployment test-deployment 
deployment.apps/test-deployment 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>

# 回滚到上一个版本
[root@k8s-master-01 k8s]# kubectl rollout undo deployment test-deployment 
deployment.apps/test-deployment rolled back

# 回滚到第一个版本(指定版本)
[root@k8s-master-01 k8s]# kubectl rollout undo deployment test-deployment --to-revision=1
deployment.apps/test-deployment rolled back
2.5、Deployment中的标签选择器
[root@k8s-master-01 k8s]# kubectl explain Deployment.spec.selector

在配置清单中,匹配标签的方式有两种:matchLabels 和 matchExpressions
matchLabels         : 精确匹配
matchExpressions    : 模糊匹配  
    IN       #  只要下图中app这个标签在下面的values里面,就归我管
    NOTIN

创建两个容器 但是只能启动一个 一个deployment中两个容器_django_02

 

 

2.6、Deployment的配置项
namespace:      命名空间
labels:        标签
annotations:    注解
replicas:       副本数

创建两个容器 但是只能启动一个 一个deployment中两个容器_Pod_03

 

 

2.7、将Django部署到k8s(django的镜像用dockerfile打包成镜像,上传到镜像仓库,用k8s拉下来)
在windows powershell中,
PS C:\Users\tiantian> django-admin.exe startproject docker
PS C:\Users\tiantian> cd .\docker\
PS C:\Users\tiantian\docker> django-admin.exe startapp app01
PS C:\Users\tiantian\docker> python3.exe .\manage.py runserver

xshell中
[root@k8s-master-01 ~]# mkdir django
[root@k8s-master-01 ~]# cd django
将docker上传到django
[root@k8s-master-01 django]# ll
drwxr-xr-x 4 root root 68 Jan  6 21:43 docker
[root@k8s-master-01 docker]# vim Dockerfile
FROM python:3.9
RUN pip install django==1.11.11
ADD ./ /opt
EXPOSE 80
WORKDIR /opt
CMD python manage.py runserver 0.0.0.0:80
[root@k8s-master-01 docker]# vim docker/settings.py 
["*"]
[root@k8s-master-01 docker]# docker build -t tiantian654321/django:v1.1 .
[root@k8s-master-01 ~]# docker login
[root@k8s-master-01 docker]# docker run -d -P tiantian654321/django:v1.1
[root@k8s-master-01 docker]# docker ps
[root@k8s-master-01 docker]# docker rm -f f6e9c4ba77b8
f6e9c4ba77b8
[root@k8s-master-01 docker]# docker push tiantian654321/django:v1.1 

vim Deployment.yaml

kind: Deployment
apiVersion: apps/v1
metadata:
  name: django
spec:
  selector:
    matchLabels:
      app: django
  template:
    metadata:
      labels:
        app: django
    spec:
      containers:
        - name: django
          image: alvinos/django:v1.1
[root@k8s-master-01 docker]# kubectl apply -f deployment.yaml
[root@k8s-master-01 docker]# kubectl get pods
报错rpc error的话就是dns解析问题,查看下vim  /etc/hosts
nameserver 8.8.8.8  #加上这句
docker pull tiantian654321/django:v1.1 
kuberctl get pods -o wide
curl -I ip   #200即成功

3、Service负载均衡器

作用就是为k8s中的Pod提供负载均衡服务。

3.1、Service实践

[root@k8s-master-01 docker]# cd docker

[root@k8s-master-01 docker]# vim deployment.yaml

[root@k8s-master-01 docker]# kubectl apply -f development.yaml

[root@k8s-master-01 docker]# kubectl get svc

[root@k8s-master-01 docker]# kubectl set image deployment/django django=tiantian654321/django:v1

解决新老交替过程出错的办法是:就绪性检查readinessProbe:

kind: Deployment
apiVersion: apps/v1
metadata:
  name: django
spec:
  selector:
    matchLabels:
      app: django
  template:
    metadata:
      labels:
        app: django
    spec:
      containers:
        - name: django
          image: alvinos/django:v1
---
kind: Service
apiVersion: v1
metadata:
  name: django
spec:
  selector:
    app: django
  ports:
    - port: 80
      targetPort: 80
      name: http
3.2、ClusterIP
只在集群内部访问。ClusterIP也是默认的Service类型。
---
kind: Service
apiVersion: v1
metadata:
  name: django
spec:
  selector:
    app: django
  ports:
    - port: 80
      targetPort: 80
      name: http
  type: ClusterIP
  clusterIP: 10.96.117.231   #可以自定义ClusterIP
3.3、NodePort
利用宿主主机的IP和端口,实现网络转发
---
kind: Service
apiVersion: v1
metadata:
  name: django
spec:
  selector:
    app: django
  ports:
    - port: 80
      targetPort: 80
      name: http
      nodePort: 30080
  type: NodePort
  clusterIP: 10.96.117.231
3.4、LoadBalancer
利用公网负载均衡,转发流量到k8s。
---
kind: Service
apiVersion: v1
metadata:
  name: django
spec:
  selector:
    app: django
  ports:
    - port: 80
      targetPort: 80
      name: http
      nodePort: 30080
  type: LoadBalancer
  clusterIP: 10.96.117.231
3.5、ExternalName
将外部的服务接入集群,使用k8s来管理外部的服务。
---
kind: Service
apiVersion: v1
metadata:
  name: externalname
spec:
  type: ExternalName
  externalName: www.baidu.com
3.6、Service别名
Service别名 跟 Service IP 同样的功能。
Service别名的组成:
    service名称.命名空间.svc.cluster.local
    django.default.svc.cluster.local
    
    
    [root@k8s-master-01 ~]# kubectl get svc -n mysql
NAME    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
mysql   ClusterIP   10.104.34.187   <none>        3306/TCP   36m
[root@k8s-master-01 ~]# kubectl run test -it --rm --image=busybox:1.28.3
If you don't see a command prompt, try pressing enter.
/ # nslookup mysql.mysql
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      mysql.mysql
Address 1: 10.104.34.187 mysql.mysql.svc.cluster.local
/ #

4、案例

4.1、数据库
[root@k8s-master-01 ~]# cd k8s
[root@k8s-master-01 k8s]# vim mysql.yaml(见下面)
[root@k8s-master-01 k8s]# kubectl apply -f mysql.yaml 
[root@k8s-master-01 k8s]# kubectl get -f mysql.yaml 
 ARTS   AGE
mysql-c5549fb5-khhs4   1/1     Running   0          14m
[root@k8s-master-01 ~]# kubectl exec -it -n mysql mysql-c5549fb5-khhs4 -- bash
root@mysql-c5549fb5-khhs4:/# mysql -uroot -p123456
mysql> create database bbs CHARACTER SET utf8 COLLATE utf8_general_ci;

mysql.yaml

---
kind: Namespace
apiVersion: v1
metadata:
  name: mysql
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: mysql
  namespace: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:5.7
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123456"
          readinessProbe:
            tcpSocket:
              port: 3306
---
kind: Service
apiVersion: v1
metadata:
  name: mysql
  namespace: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql

4.2、BBS
上传bbs
[root@k8s-master-01 k8s]# ll
-rw-r--r-- 1 root root 431029 Jan  7 10:47 bbs.zip
[root@k8s-master-01 k8s]# unzip bbs.zip
[root@k8s-master-01 k8s]# cd bbs
[root@k8s-master-01 bbs]# vim Dockerfile(见下面)

[root@k8s-master-01 bbs]# vim bbs/settings.py 
["*"]
'PASSWORD': '123456',
 'HOST': 'mysql.mysql.svc.cluster.local',  (见别名)
[root@k8s-master-01 bbs]# docker build -t tiantian654321/django:v1.2 .
[root@k8s-master-01 bbs]# docker push tiantian654321/django:v1.2
[root@k8s-master-01 k8s]# vim bbs.yaml  (见下面)
[root@k8s-master-01 k8s]# kubectl apply -f bbs.yaml

Dockerfile

[root@k8s-master-01 bbs]# vim Dockerfile 

FROM python:3.9
ADD ./ /opt
RUN pip install django==1.11.11
RUN pip install pymysql
WORKDIR /opt
EXPOSE 80
CMD python manage.py runserver 0.0.0.0:80

bbs.yaml

---
kind: Namespace
apiVersion: v1
metadata:
  name: bbs
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: bbs
  namespace: bbs
spec:
  selector:
    matchLabels:
      app: bbs
  template:
    metadata:
      labels:
        app: bbs
    spec:
      containers:
        - name: bbs
          image: tiantian654321/django:v1.2
          readinessProbe:
            tcpSocket:
              port: 80
---
kind: Service
apiVersion: v1
metadata:
  namespace: bbs
  name: bbs
spec:
  selector:
    app: bbs
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30081
  type: NodePort