Kubernetes安装部署基础简介

kubernetes,也叫k8s,是一个用于自动化部署、扩展、管理容器化应用的开源系统。

基础概念

  • Cluster

Kubernetes将集群分为一个Master和一些Node。
Master上运行着集群相关的一组进程kube-apiserver 、 kube-controller-manager和kube-scheduler,这些进程实现了整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控和纠错等管理功能,并且都是自动完成的。
Node作为集群中的工作节点,运行真正的应用程序,在Node上Kubernetes管理的最小运行单元是Pod。在Node上运行着Kubernetes的kubelet、kube-proxy服务进程,这些服务进程负责Pod的创建、启动、监控、重启、销毁,以及实现软件模式的负载均衡器。


集群结构
  • Pod

Pod运行在Node上,Node既可以是物理机也可以是虚拟机,通常一个Node上可以运行多个上百个Pod。每个Pod包含一个Pause容器和多个业务容器,业务容器共用Pause Container的网络栈和Volume挂载卷。通常将一组密切相关的业务放在一个Pod上。
Pod是Kubernetes调度的最小单位,同一Pod中的容器始终被一起调用。
并不是每个Pod和它内部运行的容器都能映射到一个Service上,只有提供服务的Pod才会被映射为一个Service。


单个Pod结构
  • Service

个人理解Service就是管理一组Pod的网络访问。它有如下特点
拥有唯一指定的名称、拥有一个虚拟IP、提供远程服务能力、被映射到提供这种服务能力的一组容器应用上(也就是一组提供服务的Pod对应一个Service)。
Service一旦创建就不会再变化。
为了建立Service和Pod之间的关系,Kubernetes首先给每个Pod贴上一个标签,然后给相应的Service定义标签选择器(Label Selector),比如标签选择器的选择条件是name=mysql,意味着该Service要作用于所有包含name=mysql 标签的Pod。


Service和Pod的映射关系
  • RC(Replication Controller)

RC控制Pod的运行。
在Kubernetes中为服务器扩容,只需为需要扩容的Service关联的Pod创建一个RC。在一个RC文件中包含以下关键信息:

  • 目标Pod定义
  • 目标Pod需要运行的副本数量
  • 要监控的Pod标签

创建好RC后,K8s通过RC中标签筛选出对应的Pod实例,并实时监控其状态和数量。如果实例数量少于定义的副本数量,则会根据在RC中定义的Pod模板创建一个新的Pod,然后将此Pod调度到合适的Node上启动运行,直到Pod实例的数量达到预定目标。这个过程完全是自动化的,无须人工干预。后续的服务升级也将通过修改RC来自动完成。

Kubernetes安装

操作系统:CentOS Linux release 7.5.1804 (Core)
Docker版本:19.03.11
Kubernetes版本:

2.1 运行时(Container runtimes)

需要在每个Node上安装运行时保证Pod可以运行,Kubernetes常用的运行时有:containerd、CPI-O、Docker。本例采用Docker。

安装Docker
#1. 设置仓库,安装需要的包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
#2. 添加Docker仓库
sudo yum-config-manager --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo
#3. 安装Docker CE
sudo yum update -y && sudo yum install -y \
  containerd.io-1.2.13 \
  docker-ce-19.03.11 \
  docker-ce-cli-19.03.11
#4. 创建/etc/docker
sudo mkdir /etc/docker
#5. 设置Docker deamon
cat <

2.2 使用kubeadm引导集群

2.2.1 安装kubeadm,kubelet,kubectl
  • kubeadm 引导集群的命令
  • kubelet 在集群中所有计算机上运行的组件,它执行诸如启动Pod和容器之类的操作。
  • kubectl 与集群通信的命令行工具。
cat <

现在kubelet每隔几秒就启动一次,因为它在一个crashloop中等待kubeadm的指令。
在使用Docker时,Kubeadm将自动监测kubelet的cgroup驱动程序,并在运行时将它设置到/var/lib/kubelet/config.yaml文件

2.2.2 kubeadm config

注意:配置文件仍然被认为是测试版,在未来的版本中可能会改变。

Kubeadm提供了配置文件用于复杂定制,同时kubeadm将配置文件以ConfigMap的形式保存到集群之中,便于后续的查询和升级工作。
kubeadm config子命令提供了对这一组功能的支持。

  1. kubeadm config upload from-file:由配置文件上传到集群中生成ConfigMap。
  2. kubeadm config upload from-flags:由配置参数生成ConfigMap。
  3. kubeadm config print init-defaults:输出kubeadm init默认参数文件的内容。
  4. kubeadm config print join-defaults:输出kubeadm join默认参数文件的内容。
  5. kubeadm config migrate:在新旧版本之间进行配置转换。
  6. kubeadm config images list:列出所需的镜像列表。
  7. kubeadm config images pull:拉取镜像到本地。
#用默认配置生成文件
[root@test-38 ~]# kubeadm config print init-defaults > init.default.yaml
2.2.3 运行kubeadm init 安装Master
  • 关闭Swap
swapoff -a
sed -i 's/.*swap.*/#&/' /etc/fstab
cat /etc/fstab
  • 运行Kubeadm init
kubeadm init
//也可自定义kubeadm config ,本例采用默认配置

等待一段时间后,Kubernetes安装Master成功,显示如下成功信息,成功信息包含了加入节点的指令和所需要的token(kubeadm join)


Master安装成功

按照信息提示执行命令,复制配置文件到普通用户的home目录下:

[root@test-38 lib]# mkdir -p $HOME/.kube
[root@test-38 lib]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@test-38 lib]# chown $(id -u):$(id -g) $HOME/.kube/config
[root@test-38 lib]# 

这样就在Master上安装了Kubernetes,但在集群内还没有可用的工作Node,并缺乏对容器的网络配置。
此时可以验证2.2.2提到的configMap

[root@test-38 ~]# kubectl get -n kube-system configmap
NAME                                 DATA   AGE
coredns                              1      99m
extension-apiserver-authentication   6      99m
kube-proxy                           2      99m
kube-root-ca.crt                     1      99m
kubeadm-config                       2      99m
kubelet-config-1.20                  1      99m

可以看到其中生成了kubeadm-config的ConfigMap对象

2.2.4安装Node,加入集群

对于新节点的添加,系统准备和kubernetes yum源的配置是一样的

kubeadm join 192.168.1.38:6443 --token qfp9bn.47raj0gk26ug6jlq     --discovery-token-ca-cert-hash sha256:ae84e70d9559f21ad42e7d9559706f597654531000ad218d0afa9ed6af83e83a 

kubeadm在Master上也安装了kubelet,在默认情况下并不参与工作负载。如果希望安装一个单机环境,可以执行下面的命令:

[root@test-38 ~]# kubectl taint nodes --all node-role.kubernetes.io/master-
node/test-38 untainted

这将从任何拥有 node-role.kubernetes.io/master taint 标记的节点中移除该标记, 包括控制平面节点,这意味着调度程序将能够在任何地方调度 Pods。

2.2.5 安装网络插件

执行kubectl get nodes,会发现Master处于NotReady的状态,这是因为还没有安装CNI网络插件:

[root@test-38 ~]# kubectl get nodes
NAME      STATUS     ROLES                  AGE   VERSION
test-38   NotReady   control-plane,master   24m   v1.20.4

安装CNI网络插件,这里选择的是weave

kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
2.2.6 验证kubernetes集群是否安装完成
kubectl get pods --all-namespaces

如果发现有状态错误的Pod,则可以执行kubectl --namespace=kube-systemdescribe pod来查看错误原因,常见的错误原因是镜像没有下载完成。

2.2.7 部署应用

使用 kubernetes create deployment部署应用:

kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1

部署应用做了以下两件事:

  • 寻找合适的可以运行应用实例的Node
  • 安排应用程序在该节点上运行
  • 配置集群以在需要时在新节点上重新安排实例
    查看deployment
[root@test-38 ~]# kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/1     1            1           103m

2.2.8 访问应用

默认情况下,所有Pod只能在集群内部访问,当使用kubectl时,我们正在通过API端点进行交互来和我们的程序进行通信。

  1. 通过代理访问API

kubectl可以创建一个代理,该代理会将通信转发到集群范围的专用网络

[root@test-38 ~]# kubectl proxy
Starting to serve on 127.0.0.1:8001

现在我们有了一个我们主机和kubernetes集群的连接,这个代理允许我们通过API进行访问。

[root@test-38 ~]# curl http://localhost:8001/version
{
  "major": "1",
  "minor": "20",
  "gitVersion": "v1.20.4",
  "gitCommit": "e87da0bd6e03ec3fea7933c432i63d151aafdusj",
  "gitTreeState": "clean",
  "buildDate": "2021-02-18T16:03:00Z",
  "goVersion": "go1.15.8",
  "compiler": "gc",
  "platform": "linux/amd64"
}

API 服务器将基于Pod名称自动为每个Pod创建一个端点,该端点也可以通过代理进行访问。
首先我们要现获取Pod名称,然后将名称存储在环境变量POD_NAME:

[root@test-38 ~]# export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
[root@test-38 ~]# echo Name of the Pod: $POD_NAME
Name of the Pod: kubernetes-bootcamp-57978f5f5d-jcn7k

使用kubectl logs $POD_NAME查看pod日志

[root@test-38 ~]# kubectl logs  kubernetes-bootcamp-57978f5f5d-jcn7k
Kubernetes Bootcamp App Started At: 2021-03-01T08:07:32.804Z | Running On:  kubernetes-bootcamp-57978f5f5d-jcn7k 

还可以在container内部执行命令,具体可以参考https://kubernetes.io/docs/tutorials/kubernetes-basics/explore/explore-interactive/

  1. 从外部访问应用
    查看现有的service可以看到,系统有一个默认创建的service。
[root@test-38 ~]# kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1            443/TCP   2d17h

要访问应用只能访问容器的8080端口,我们要将容器的8080端口映射到节点的端口。

[root@test-38 ~]# kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed
[root@test-38 ~]# kubectl get services
NAME                  TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1              443/TCP          2d17h
kubernetes-bootcamp   NodePort    10.99.65.217           8080:30691/TCP   8s

现在可以看到我们新运行了一个叫kubernetes-bootcamp的service,可以看到应用被映射到节点的30691端口,端口号是随机分配的,可以执行如下命令访问应用:

[root@test-38 ~]# curl localhost:30691
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-57978f5f5d-jcn7k | v=1

Deployment会自动为我们的Pod创建一个标签

[root@test-38 ~]# kubectl describe deployments

使用标签获取pod列表:

[root@test-38 ~]# kubectl get pods -l app=kubernetes-bootcamp
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-57978f5f5d-jcn7k   1/1     Running   0          19h

删除service——delete service

[root@test-38 ~]# kubectl delete service -l app=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted
2.2.9 Scale 应用

默认情况下只会运行一个副本,可以通过kubectl get deployments查看副本

[root@test-38 ~]# kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/1     1            1           22h

READY 显示的是当前副本和所需副本的比率
UP-TO-DATE 显示的是已更新到所需状态的副本数量
AVAILABLE 显示应用程序有多少个副本可供用户使用
AGE 显示应用程序已运行的时间

现在我们扩展复制集到4个

[root@test-38 ~]# kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.apps/kubernetes-bootcamp scaled
[root@test-38 ~]# kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   4/4     4            4           22h

现在我们查看pod的情况,可以看到当前Pod已经增加到4个

[root@test-38 ~]# kubectl get pods -o wide
NAME                                   READY   STATUS    RESTARTS   AGE     IP          NODE      NOMINATED NODE   READINESS GATES
kubernetes-bootcamp-57978f5f5d-42tp5   1/1     Running   0          2m10s   10.32.0.5   test-38              
kubernetes-bootcamp-57978f5f5d-8k4w4   1/1     Running   0          2m10s   10.32.0.7   test-38              
kubernetes-bootcamp-57978f5f5d-jcn7k   1/1     Running   0          22h     10.32.0.4   test-38              
kubernetes-bootcamp-57978f5f5d-pkfgq   1/1     Running   0          2m10s   10.32.0.6   test-38              

可以验证一下复制集是否进行负载均衡,使用curl进行访问应用,可以各个请求每次发送到不同的Pod,四个副本轮询处理,实现负载均衡

[root@test-38 ~]# curl localhost:32230
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-57978f5f5d-pkfgq | v=1
[root@test-38 ~]# curl localhost:32230
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-57978f5f5d-jcn7k | v=1
[root@test-38 ~]# curl localhost:32230
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-57978f5f5d-42tp5 | v=1
2.2.10 滚动更新

使用kubectl describe pods 查看现在的image版本信息,现在将image升级到v2

 kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2

通过kubectl get pods可以看到滚动更新的过程:v1的Pod逐渐删除,同时启动新的v2 Pod。
回退版本使用kubectl rollout undo命令,rollout命令将部署还原到先前的已知状态(映像的v2)。 更新是版本控制的,您可以还原到以前任何已知的部署状态。

kubectl rollout undo deployments/kubernetes-bootcamp

完结撒花~

参考:《Kubenetes权威指南》、https://kubernetes.io

你可能感兴趣的:(Kubernetes安装部署基础简介)