Kubernetes基础

Kubernetes简称K8S,用于自动部署扩展管理容器化应用程序的开源系统。 核心特点;

  • 服务发现与负载均衡:无需修改应用程序即可使用陌生的服务发现机制
  • 存储编排:自动挂载所选存储系统,包括本地存储
  • Secret和配置管理:部署更新Secrets和应用程序的配置时不必重新构建容器镜像,且不必将软件堆栈配置中的秘密信息暴露出来
  • 批量执行:除了服务外,Kubernetes还可管理批处理和CI工作负载,在期望时替换掉失效的容器
  • 水平扩缩:使用一个简单的命令、一个UI或基于CPU使用情况自动对应用程序进行扩缩
  • 自动化上线和回滚:Kubernetes会分步骤地将针对应用或其配置的更改上线,同时监视应用程序运行状况以确保不会同时终止所有实例
  • 自动装箱:根据资源需求和其他约束自动放置容器,同时避免影响可用性
  • 自我修复:重新启动失败的容器,在节点死亡时替换并重新调度容器,杀死不响应用户定义的健康检查的容器

K8S核心架构原理

K8S属于主从设备模型即Master-Slave架构,Master节点负责核心调度管理运维Slave节点执行用户程序主节点一般被称为Master NodeHead Node从节点被称为Worker Node或Node。

Master NodeWorker Node是分别安装了K8S的Master和Woker组件的实体服务器,每个Node都对应了一台实体服务器,虽然Master Node可和其中一个Worker Node安装在同一台服务器,但建议Master Node单独部,所有Master Node和Worker Node组成了K8S集群,同一个集群可能存在多个Master NodeWorker Node

Master Node包含的组件
  • API ServerK8S请求入口服务,API Server负责接收K8S所有包括来自UI界面CLI命令行工具的请求,然后根据用户具体请求,去通知其他组件干活
  • Scheduler:K8S所有Worker Node的调度器,当用户部署服务时,Scheduler会选择最合适的Worker Node服务器来部署服务
  • Controller Manager:K8S所有Worker Node的监控器,Controller Manager有很多具体的Controller, Node Controller、Service Controller、Volume Controller等。Controller负责监控调整Worker Node上部署的服务的状态,如用户要求A服务部署2个副本,若当其中一个服务挂了时,Controller会马上调整,让 Scheduler再选择一个Worker Node重新部署服务
  • etcd:K8S的存储服务,存储了K8S的关键配置用户配置API Server具备读写权限,其他组件必须通过API Server接口才能读写数据
Worker Node包含的组件
  • KubeletWorker Node监视器Master Node的通讯器,Kubelet是Master Node安插在Worker Node上的眼线,它会定期向Master Node汇报自己Node上运行的服务的状态,并接受来自Master Node的指示采取调整措施,负责控制所有容器的启动停止,保证节点工作正常
  • Kube-Proxy:K8S的网络代理负责Node在K8S的网络通讯、以及对外部网络流量的负载均衡
  • Container Runtime:Worker Node的运行环境,即安装了容器化所需的软件环境确保容器化程序能够跑起来,如Docker Engine运行环境
协同工作流程

用K8S部署Nginx的过程中,K8S内部各组件的协同工作流程,若在Master节点执行一条命令kubectl create deployment nginx --image=nginx要Master部署一个nginx应用

  • 该命令首先发到Master节点的网关API Server
  • API Server将命令请求交给Controller Mannager进行控制
  • Controller Mannager进行应用部署解析,生成一次部署信息,并通过API Server将信息存入etcd
  • Scheduler调度器通过API Serveretcd存储中获取要部署的应用,开始调度看哪个节点有资源适合部署
  • Scheduler把计算出来的调度信息通过API Server再存入etcd
  • 每个Node节点的监控组件kubelet,随时和Master保持联系,给API Server发送请求不断获取最新数据,拿到Master节点存储在etcd中的部署信息
  • 若node2的kubelet拿到部署信息,显示其自己节点要部署该nginx应用
  • kubelet监控组件就自己run一个应用在当前机器上,并随时给Master汇报当前应用的状态信息
  • Node和Master也是通过Master的API Server组件联系的
  • 每个机器上的kube-proxy能知道集群的所有网络,只要Node访问别人或别人访问Node,Node上的kube-proxy网络代理自动计算进行流量转发

K8S核心概念

Deployment

Deployment负责创建更新应用程序的实例。创建Deployment后,Kubernetes Master将应用程序实例调度到集群中的各个节点上,若托管实例的节点关闭或被删除,Deployment控制器会将该实例替换为群集中另一个节点上的实例。这提供了一种自我修复机制来解决机器故障维护问题。

Pod

Pod相当于逻辑主机的概念,负责托管应用实例,包括一个多个应用程序容器如Docker,以及这些容器的一些共享资源,共享存储网络运行信息等。

Service

Service是一个抽象层,它定义了一组Pod的逻辑集,并为这些Pod支持外部流量暴露负载平衡服务发现。尽管每个Pod都有一个唯一的IP地址,但若没有Service,这些IP不会暴露在群集外部,Service允许应用程序接收流量。Service也可用在ServiceSpec标记type的方式暴露,type类型如下:

  • ClusterIP默认,在集群的内部IP上公开Service,这种类型使得Service只能从集群内访问
  • NodePort:使用NAT在集群中每个选定Node的相同端口上公开Service,使用<NodeIP>:<NodePort>从集群外部访问Service,是ClusterIP的超集
  • LoadBalancer:在当前云中创建一个外部负载均衡器若支持的话,并为Service分配一个固定的外部IP,是NodePort的超集
  • ExternalName:通过返回带有该名称的CNAME记录公开Service,不使用代理,使用任意名称,由spec中的externalName指定

Service是K8S服务的核心屏蔽了服务细节统一对外暴露服务接口,如一个服务A部署了3个备份,即3个Pod,对于用户来说,只需要关注一个Service的入即可,而不需要操心究竟应该请求哪一个Pod。外部用户不需要感知因为Pod上服务的意外崩溃、K8S重新拉起Pod而造成的IP变更,外部用户也不需要感知因升级变更服务带来的Pod替换而造成的IP变化。

Service还可以做流量负载均衡主要负责K8S集群内部的网络拓扑集群外部访问集群内部可通过Ingress来完成,Ingress是对集群中服务的外部访问进行管理的API对象,典型的访问方式是HTTP,Ingress可提供负载均衡SSL终结基于名称的虚拟托管,Ingress是整个K8S集群的接入层,负责集群内外通讯,Ingress和Service的网络拓扑关系图如下:

K8S安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld

# 关闭selinux
sed -i 's/enforcing/disabled/' /etc/selinux/config # 永久关闭
setenforce 0 # 临时关闭

# 关闭swap
swapoff -a # 临时关闭
vim /etc/fstab # 永久关闭,注释掉/etc/fstab文件下面这行代码
# /dev/mapper/centos‐swap swap swap defaults 0 0

systemctl reboot # 重启生效
free -m # 查看下swap交换区是否都为0,如果都为0则swap关闭成功

# 给机器设置主机名
hostnamectl set-hostname <hostname>

# 给机器名称配置hosts
vim /etc/hosts
# 添加如下行
192.168.0.180 eleven

# 将桥接的IPv4流量传递到iptables
vim /etc/sysctl.d/k8s.conf
# 添加下面两行配置
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

sysctl --system # 生效

# 设置时间同步
yum install ntpdate -y
ntpdate time.windows.com

# 添加k8s yum源
vim /etc/yum.repos.d/kubernetes.repo
# 添加如下配置
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg

# 若之前安装过k8s,先卸载旧版本
yum remove -y kubelet kubeadm kubectl
# 查看可以安装的版本
yum list kubelet --showduplicates | sort -r
# 安装kubelet、kubeadm、kubectl指定版本,这里使用kubeadm方式安装k8s集群
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0

# 开机启动kubelet
systemctl enable kubelet
systemctl start kubelet

# 在k8s的Master机器上执行初始化操作
kubeadm init --apiserver-advertise-address=192.168.0.180 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.18.0 --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16

# 配置使用kubectl命令工具(类似docker这个命令)
mkdir -p $HOME/.kube
chmod 666 /etc/kubernetes/admin.conf
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 查看kubectl是否能正常使用,此时节点状态为NotReady,安装Pod网络插件后才会变为Ready状态
kubectl get nodes

# 安装Pod网络插件
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
# 若上面这个calico网络插件安装不成功可以试下下面这个
# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kubeflannel.yml

# 将node节点加入进Master节点的集群里,复制kubeadm init命令执行后的输出中的kubeadm join内容
kubeadm join 192.168.65.160:6443 --token hbovty.6x82bkdlsk6dfy32 \ --discovery-token-ca-cert-hash sha256:659511b431f276b2a5f47397677b1dff74838ae5eb18e24135e6dae1b8c45840

# 将Master也当作Node使用,xxx-nodename表示节点名称,或主机IP,也可使用--all参数
kubectl taint node xxx-nodename node-role.kubernetes.io/master-
kubectl taint nodes --all node-role.kubernetes.io/master-
# 将Master恢复成Master Only状态,xxx-nodename表示节点名称,或主机IP
kubectl taint node xxx-nodename node-role.kubernetes.io/master="":NoSchedule

# 要删除k8s-node1节点,首先在master节点上依次执行以下两个命令
kubectl drain k8s‐node1 --delete-local-data --force --ignore-daemonsets
kubectl delete node k8s-node1
# 在k8s-node1这个Node节点上执行如下命令,这样该节点即完全从k8s集群中脱离开来
kubeadm reset

# 忘记令牌或新的节点加入,在master上执行下面的命令生成新的令牌
kubeadm token create --print-join-command

# 查看kubelet日志
journalctl -xefu kubelet

systemctl daemon-reload && systemctl restart kubelet
命令补全
1
2
3
4
yum -y install bash-completion
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

K8S部署应用

kubectlAPI Server客户端工具,工作在命令行下,能够连接API Server实现各种增删改查等操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 创建一次deployment部署
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
# 查看Nginx的pod和service信息
kubectl get pod,svc -o wide

# my‐tomcat表示pod的名称 --image表示镜像的地址
kubectl create deployment my-tomcat --image=tomcat:7.0.75-alpine
kubectl get deployment
kubectl get pod -o wide

# 查看Pod打印的日志
kubectl logs my-tomcat-6d9cf656c4-45xk5
# 使用exec可在Pod的容器中执行命令,使用env命令查看环境变量
kubectl exec my-tomcat-6d9cf656c4-45xk5 -- env
# 查看容器的根目录下面内容
kubectl exec my-tomcat-6d9cf656c4-45xk5 -- ls /
# 进入Pod容器内部并执行bash命令,若想退出容器可以使用exit命令
kubectl exec -it my-tomcat-6d9cf656c4-45xk5 -- sh

# 在集群外是无法访问Pod的,需要创建一个service服务,才能让外部客户端可访问Pod
# --name指定service名称,若端口暴露类型为NodePort,可通过集群内任意一台主机加暴露端口进行访问
kubectl expose deployment my-tomcat --name=tomcat --port=8080 --type=NodePort
#查看service信息,port信息里冒号后面的端口号就是对集群外暴露的访问接口
kubectl get svc -o wide
# 查看pod信息,‐w意思是一直等待观察pod信息的变动
kubectl get pod -w
# 查看pod、deployment、service等所有信息
kubectl get all -o wide

# 删除刚刚创建的Pod,k8s会重新启动一个新的pod,这是k8s的服务自愈功能
kubectl delete pod my-tomcat-6d9cf656c4-45xk5
# 真正删除pod
kubectl delete deployment my-tomcat
# 删除service
kubectl delete service tomcat
扩容缩容
1
2
3
4
# 扩容到3个pod
kubectl scale --replicas=3 deployment my-tomcat
# 缩容到2个pod
kubectl scale --replicas=2 deployment my-tomcat
滚动升级与回滚

滚动升级并不是一次性将多个pod全部停掉升级,而是一个一个的滚动升级

1
2
3
4
5
6
7
# 滚动升级将tomcat版本由tomcat:7.0.75-alpine升级到tomcat:8.0.41-jre8-alpine
kubectl set image deployment my-tomcat tomcat=tomcat:8.0.41-jre8-alpine

# 查看历史版本
kubectl rollout history deploy my-tomcat
# 回滚到上一个版本,也可通过--to-revision参数可指定回退的版本
kubectl rollout undo deployment my-tomcat
标签

通过给资源添加Label,可方便地管理资源,如Deployment、Pod、Service等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看Deployment中所包含的Label,该命令是查询deployment详细信息,该信息中包括Label信息
kubectl describe deployment my-tomcat
# 通过Label查询Pod
kubectl get pods -l app=my-tomcat
# 通过Label查询services
kubectl get services -l app=my-tomcat
# 给Pod添加Label
kubectl label pod my-tomcat-6d9cf656c4-45xk5 version=v1
# 查看Pod的详细信息,包括Label信息
kubectl describe pods my-tomcat-6d9cf656c4-45xk5
# 通过Label查询Pod
kubectl get pods -l version=v1
# 通过Label删除服务
kubectl delete service -l app=test-service
问题排查
1
2
3
4
5
6
7
8
9
10
# 查看Pod内部某个container打印的日志
kubectl log ${POD_NAME} -c ${CONTAINER_NAME}
# 查看Pod打印的日志
kubectl logs my-tomcat-6d9cf656c4-45xk5
# 使用exec可在Pod的容器中执行命令,使用env命令查看环境变量
kubectl exec my-tomcat-6d9cf656c4-45xk5 -- env
# 查看容器的根目录下面内容
kubectl exec my-tomcat-6d9cf656c4-45xk5 -- ls /
# 进入Pod容器内部并执行bash命令,若想退出容器可以使用exit命令
kubectl exec -it my-tomcat-6d9cf656c4-45xk5 -- sh

K8S中的资源

K8S中所有内容都抽象为资源, 资源实例化之后叫做对象,上面说的那些核心概念都是
K8S中的资源:

  • workload工作负载型资源PodReplicaSetDeploymentStatefulSetDaemonSet等等
  • ServiceDiscovery LoadBalance服务发现及负载均衡型资源ServiceIngress等等
  • 配置与存储型资源Volume存储卷、CSI容器存储接口、可扩展各种各样的第三方存储卷
  • 特殊类型的存储卷ConfigMap当配置中心来使用的资源类型、Secret保存敏感数据、DownwardAPI把外部环境中的信息输出给容器
  • 集群级资源NamespaceNodeRoleClusterRoleRoleBinding角色绑定、ClusterRoleBinding集群角色绑定
  • 元数据型资源HPA即Pod水平扩展、PodTemplate即Pod模板,用于让控制器创建Pod时使用的模板、LimitRange用来定义硬件资源限制
资源清单

上面直接用命令创建deploymentpodservice这些资源,在k8s中一般都会使用yaml格式的文件来创建符合预期期望的资源,这样的yaml文件一般称为资源清单

使用资源清单yaml来创建k8s的资源对象,用yaml创建deployment资源的对象,可用创建deployment的命令加上参数--dry-run -o yaml就可以输出这次部署的资源清单yaml

1
kubectl create deployment my-tomcat --image=tomcat:7.0.75‐alpine --dry-run -o yaml

对上面的yaml适当的修改下保存为文件tomcat-deployment-demo.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: my-tomcat-yaml
name: my-tomcat-yaml #修改deployment的名称
spec:
replicas: 2 # 修改pod副本为两个
selector:
matchLabels:
app: my-tomcat-yaml
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: my-tomcat-yaml
spec:
containers:
- image: tomcat:7.0.75-alpine
name: tomcat
resources: {}
status: {}
1
2
3
4
# 用yaml文件来创建这次部署
kubectl apply -f tomcat-deployment-demo.yaml
# 用yaml创建service资源的对象
kubectl expose deployment my-tomcat-yaml --name=tomcat --port=8080 --type=NodePort --dry-run -o yaml

yaml创建service资源的对象,保存为文件tomcat-service-demo.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: my-tomcat-yaml
name: tomcat-service-yaml # 修改Service名称
spec:
ports:
- port: 8081 # service虚拟ip对应的端口,在集群内网机器可用service的虚拟ip加该端口号访问服务
protocol: TCP
targetPort: 8080 # pod暴露的端口,一般与pod内部容器暴露的端口一致
selector:
app: my-tomcat-yaml
type: NodePort
status:
loadBalancer: {}
1
2
3
4
5
6
# 用yaml文件来创建service
kubectl apply -f tomcat-service-demo.yaml
# 针对已有资源输出资源清单yaml,使用-o参数加yaml,可将资源的配置以yaml的格式输出出来,也可使用json,输出为json格式
kubectl get pod nginx-deploy-7db697dfbd-2qh7v -o yaml
kubectl get service nginx -o yaml
kubectl get deployment nginx -o yaml

K8S高级特性

K8S中还有一些高级特性如弹性扩缩应用滚动更新、配置管理、存储卷、网关路由等。

ReplicaSet

ReplicaSet保任何时间都有指定数量的Pod副本在运行,通常用来保证给定数量的、完全相同的Pod的可用性。建议使用Deployment来管理ReplicaSet,而不是直接使用ReplicaSet

ConfigMap

ConfigMap是一种API对象,用来将非机密性的数据保存到键值对中。使用时Pod可将其用作环境变量命令行参数存储卷中的配置文件。使用ConfigMap将配置数据和应用程序代码分开

Volume

Volume指的是存储卷包含可被Pod中容器访问的数据目录,容器中文件在磁盘上是临时存放,当容器崩溃时文件会丢失,同时无法在多个Pod中共享文件,通过使用存储卷可以解决这两个问题,常用存储卷:

  • configMap提供向Pod注入配置数据的方法,ConfigMap对象中存储的数据可被configMap类型的卷引用,然后被Pod中运行的容器化应用使用
  • emptyDir:emptyDir卷可用于存储缓存数据当Pod分派到某个Node上时emptyDir卷会被创建,且Pod在该节点上运行期间卷一直存在当Pod被从节点上删除时emptyDir卷中的数据也会被永久删除
  • hostPath将主机节点文件系统上的文件或目录挂载到Pod中,在Minikube中的主机指的是Minikube所在虚拟机
  • local:代表某个被挂载的本地存储设备,如磁盘、分区或目录,local卷只能用作静态创建的持久卷,尚不支持动态配置
  • nfs将NFS网络文件系统挂载到Pod中
  • persistentVolumeClaim:将持久卷PersistentVolume挂载到Pod中,持久卷是集群中的一块存储,可以由管理员事先供应,或使用存储类Storage Class来动态供应,持久卷是集群资源类似于节点

Ingress

通过Ingress资源可实现类似Nginx的基于域名访问从而实现Pod的负载均衡访问,进入ingress-nginx将里面内容复制保存到k8s master机器上的ingress-controller.yaml文件中,修改镜像地址。

1
2
3
4
5
6
# 安装ingress
kubectl apply -f ingress-controller.yaml
# 查看是否安装成功
kubectl get pods -n ingress-nginx -o wide
# 查看日志
kubectl logs -f nginx-ingress-controller-2dvwn -n ingress-nginx

配置ingress访问规则,类似配置nginx的代理转发配置,让ingress将域名tomcat.eleven.com转发给后端的tomcat-service-yaml服务,新建ingress-tomcat.yaml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: web-ingress
spec:
rules:
- host: tomcat.eleven.com # 转发域名
http:
paths:
- path: /
backend:
serviceName: tomcat-service-yaml # service名称
servicePort: 8081 # service的端口
1
2
3
4
5
6
7
8
9
# 生效规则
kubectl apply -f ingress-tomcat.yaml
# 卸载资源
kubectl delete -f ingress-tomcat.yaml
# 查看生效的ingress规则
kubectl get ing
kubectl describe ing web-ingress
# 在hosts中配置:192.168.0.180 tomcat.eleven.com
echo "192.168.0.180 tomcat.eleven.com" >> /etc/hosts

ConfigMap

ConfigMap允许将配置文件镜像文件分离,将ConfigMap属性注入到Pod的环境变量中去,使容器化的应用程序具有可移植性。添加nginx-config.yaml配置文件用于创建ConfigMap,ConfigMap名称为nginx-config,配置信息存放在data节点下:

1
2
3
4
5
6
7
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
namespace: default
data:
nginx-env: test
1
2
3
4
5
6
# 应用nginx-config.yaml文件创建ConfigMap
kubectl create -f nginx-config.yaml
# 获取所有ConfigMap
kubectl get configmap
# 通过yaml格式查看ConfigMap中的内容
kubectl get configmaps nginx-config -o yaml

添加配置文件nginx-deployment.yaml用于创建Deployment,部署一个Nginx服务,在Nginx的环境变量中引用ConfigMap中的属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.10
ports:
- containerPort: 80
env:
- name: NGINX_ENV # 在Nginx中设置环境变量
valueFrom:
configMapKeyRef:
name: nginx-config # 设置ConfigMap的名称
key: nginx-env # 需要取值的键
1
2
3
4
# 应用配置文件文件创建Deployment
kubectl apply -f nginx-deployment.yaml
# 创建成功后查看Pod中的环境变量,发现NGINX_ENV变量已经被注入了
kubectl exec nginx-deployment-7cf97748c4-tcq5v -- env

存储卷的使用

通过存储卷可把外部数据挂载到容器中去,供容器中的应用访问,这样就算容器崩溃了,数据依然可以存在,使用Docker部署Nginx时,将Nginx的html、logs、conf目录从外部挂载到容器中:

1
2
3
4
5
docker run -p 80:80 --name nginx \
-v /data/nginx/html:/usr/share/nginx/html \
-v /data/nginx/logs:/var/log/nginx \
-v /data/nginx/conf:/etc/nginx \
-d nginx:1.10

Minikube可认为是一台虚拟机,可用Minikubessh命令来访问它

1
2
3
4
5
6
7
minikube ssh
# Minikube中默认有一个docker用户,我们先重置下它的密码
sudo passwd docker
# 在Minikube中创建data目录
midir /home/docker/data
# 把Nginx数据目录复制到Minikube中,才能实现目录的挂载,注意docker用户只能修改/home/docker目录中的文件,通过scp命令来复制文件
scp -r /home/macro/data/nginx docker@192.168.0.180:/home/docker/data/nginx

添加nginx-volume-deployment.yaml配置文件用于创建Deployment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-volume-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.10
ports:
- containerPort: 80
volumeMounts:
- mountPath: /usr/share/nginx/html
name: html-volume
- mountPath: /var/log/nginx
name: logs-volume
- mountPath: /etc/nginx
name: conf-volume
volumes:
- name: html-volume
hostPath:
path: /home/docker/data/nginx/html
type: Directory
- name: logs-volume
hostPath:
path: /home/docker/data/nginx/logs
type: Directory
- name: conf-volume
hostPath:
path: /home/docker/data/nginx/conf
type: Directory
1
2
3
4
# 应用配置文件创建Deployment
kubectl apply -f nginx-volume-deployment.yaml
# 应用配置文件创建Service
kubectl apply -f nginx-service.yaml

添加nginx-service.yaml配置文件用于创建Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
nodePort: 30080

K8S与Docker

Docker作为非常流行的容器技术,经常有文章说它被K8S弃用了,取而代之的是另一种容器技术containerd,containerd只是从Docker中分离出来的底层容器运行时,使用起来和Docker并没有什么区别,从Docker转型containerd非常简单,只要把之前Docker命令中的docker改为crictl基本就可以了用法一样。

K8S发布CRI即Container Runtime Interface统一了容器运行时接口,凡是支持CRI的容器运行时,皆可作为K8S的底层容器运行时,若K8S使用Docker作为K8S容器运行时的话,kubelet需要先要通过dockershim去调用Docker,再通过Docker去调用containerd,若使用containerd作为K8S容器运行时的话,由于containerd内置了CRI插件,kubelet可直接调用containerd,使用containerd不仅调用链变短了性能提高了,且资源占用也会变小,毕竟Docker不是一个纯粹的容器运行时,具有大量其他功能,未来Docker可能自己直接实现K8S的CRI接口来兼容K8S的底层使用。

实战

Docker部署过的eureka应用为例,首先将镜像发布到镜像仓库中,然后创建用于创建Deployment的配置文件eureka-app-deployment.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
apiVersion: apps/v1
kind: Deployment
metadata:
name: eureka-app-deployment
labels:
app: eureka-app
spec:
replicas: 1
selector:
matchLabels:
app: eureka-app
template:
metadata:
labels:
app: eureka-app
spec:
containers:
- name: eureka-app
# 指定Docker Hub中的镜像地址
image: 3120130802229/eleven-eureka-server:0.0.1
# Always总是拉取镜像,IfNotPresent(默认该值) 本地有则使用本地镜像,Never只使用本地镜像,从不拉取,即使本地没有镜像
imagePullPolicy: Always
ports:
- containerPort: 8761
env:
- name: TZ
value: Asia/Shanghai
- name: LOG_FILE
value: /var/logs
volumeMounts:
- mountPath: /var/logs
name: log-volume
volumes:
- name: log-volume
hostPath:
path: /data/k8s-app/eureka/logs
type: DirectoryOrCreate
dnsPolicy: Default # 继承Pod所在宿主机的DNS设置,使pod能访问外网

创建用于创建Service的配置文件eureka-app-service.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
name: eureka-app-service
spec:
type: NodePort
selector:
app: eureka-app
ports:
- name: http
protocol: TCP
port: 8761 # service的端口
targetPort: 8761 # pod的端口,一般与pod内部容器的服务端口一致
1
2
3
4
# 通过应用配置文件来创建Deployment
kubectl apply -f eureka-app-deployment.yaml
# 通过应用配置文件来创建Service
kubectl apply -f eureka-app-service.yaml