什么是Kubernetes

  • Kubernetes是Google 2014年创建管理的,是Google 10多年大规模容器管理技术Borg的开源版本。

  • Kubernetes(K8S)是Google开源的容器集群管理系统,其设计源于Google在容器编排方面积累的丰富经验,并结合社区创新的最佳实践。

  • K8S在Docker容器技术的基础之上,大大地提高了容器化部署应用简单高效。并且具备了完整的集群管理能力,例如服务发现、资源配额、缩容扩容、动态更新、持久化存储、监控、日志等,涵盖项目周期的各个环节。

  • 经过这几年的快速发展,K8S已经成为建设容器云平台的首选方案

  • Kubernetes的名字来自希腊语,意思是“舵手” 或 “领航员”。K8s是将8个字母“ubernete”替换为“8”的缩写。

Kubernetes与docker联系

  • Docker是一个容器引擎,用于运行容器,Kubernetes是一个容器编排系统,不具备容器引擎功能,相比Docker是一个更高级封装,而他们在一起堪称珠联璧合,一起搞大事!如图:

Kubernetes与docker联系

Kubernetes 介绍

  • 存储编排
    Kubernetes 允许您自动挂载您选择的存储系统,例如本地存储、公共云提供商、NFS等。

  • 应用程序健康检查
    容器内服务可能进场阻塞无法处理请求,可以设置监控检查策略保证 应用健壮性

  • 复制应用程序实例
    控制器维护着pod的副本数量,保证一个Pod或一组同类的Pod数量始终可用

  • 弹性伸缩
    根据设定的指标(CPU利用率)自动缩放Pod副本数量

  • 服务发现
    使用环境变量或DNS服务插件保证容器中程序发现Pod入口访问地址

  • 负载均衡
    一组Pod副本分配一个私有的集群IP地址,负载均衡转发请求到后端容器。在集群里内部其他Pod可通过这个ClusterIp访问应用

  • 滚动更新
    更新服务不中断,一次更新一个pod

  • 服务编排
    通过文件描述部署服务,使得应用程序部署变得更高效

  • 资源监控
    Node节点组件集成cAdvisor资源收集工具,可通过Heapster汇总整个集群节点资源数据,然后存储到InFluxDB时序数据库,再由Grafana展示

  • 提供认证和授权
    支持角色访问权限(RBAC)

  • 日志访问
    可以查询容器运行日志

Kubernetes不是什么?

  • Kubernetes并不是传统的PaaS(平台即服务)系统。

  • Kubernetes不限制支持应用的类型,不限制应用框架。不限制受支持的语言runtimes (例如, Java, Python, Ruby),满足12-factor applications 。不区分 “apps” 或者“services”。 Kubernetes支持不同负载应用,包括有状态、无状态、数据处理类型的应用。只要这个应用可以在容器里运行,那么就能很好的运行在Kubernetes上。

  • Kubernetes不提供中间件(如message buses)、数据处理框架(如Spark)、数据库(如Mysql)或者集群存储系统(如Ceph)作为内置服务。但这些应用都可以运行在Kubernetes上面。

  • Kubernetes不部署源码不编译应用。持续集成的 (CI)工作流方面,不同的用户有不同的需求和偏好的区域,因此,我们提供分层的 CI工作流,但并不定义它应该如何工作。

  • Kubernetes允许用户选择自己的日志、监控和报警系统。

  • Kubernetes不提供或授权一个全面的应用程序配置 语言/系统(例如,jsonnet)。

  • Kubernetes不提供任何机器配置、维护、管理或者自修复系统。

Kubernetes组件

Kubernetes组件

Kubernetes组件–Master 组件

  • Master 组件提供集群的控制平面
    Master 组件对集群进行全局决策(例如,调度),并检测和响应集群事件(例如,当不满足部署的 replicas 字段时,启动新的 pod)。
  • kube-apiserver
    主节点上负责提供 Kubernetes API 服务的组件;它是 Kubernetes 控制面的前端。
  • etcd
    etcd 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。
  • kube-scheduler
    主节点上的组件,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点让 Pod 在上面运行。
    调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。
  • kube-controller-manager
    在主节点上运行控制器的组件。
    从逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。
    这些控制器包括:
    • 节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应。
    • 副本控制器(Replication Controller): 负责为系统中的每个副本控制器对象维护正确数量的 Pod。
    • 端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入 Service 与 Pod)。
    • 服务帐户和令牌控制器(Service Account & Token Controllers): 为新的命名空间创建默认帐户和 API 访问令牌

kube-controller-manager

  • 容器运行环境(Container Runtime)
    容器运行环境是负责运行容器的软件。–docker

Kubernetes组件–Node 组件

  • kubelet
    一个在集群中每个节点上运行的代理。它保证容器都运行在 Pod 中。
    kubelet 接收一组通过各类机制提供给它的 PodSpecs,确保这些 PodSpecs 中描述的容器处于运行状态且健康。kubelet 不会管理不是由 Kubernetes 创建的容器。

  • kube-proxy
    kube-proxy 是集群中每个节点上运行的网络代理,实现 Kubernetes Service 概念的一部分。
    kube-proxy 维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信。
    如果有 kube-proxy 可用,它将使用操作系统数据包过滤层。否则,kube-proxy 会转发流量本身。

  • 容器运行环境(Container Runtime)
    容器运行环境是负责运行容器的软件。–docker

Kubernetes 核心对象概念

  • pod
    Pod是最小部署 单元,一个Pod有一个或多个容器组成,Pod中容器共享存储和网站,在同一个DOcker主机上运行

  • Service
    Service一个应用服务抽象,定义了Pod逻辑集合和访问这个Pod集成的策略
    Service代理Pod集合对外表现是为一个访问入口,分配一个集群Ip地址,来自这个Ip的请求将负载均衡转发后端Pod中容器
    Servie 通过Label Selector 选择一组Pod提供服务

  • Volume
    数据卷,供于Pod使用的数据

  • Namespace
    命名空间将对象逻辑上分配到不同Namespace,可以不同项目、用户等区分管理,从而实现多租户。命名空间也成为虚拟集群

  • Label
    标签用于区分对象(比如Pod service),键/值对存在,每个对象可以有多个标签,通过标签关联对象

  • ReplicaSet
    下一代Replication Controller,确保任何给定时间指定Pod副本数量,并提供声明式更新等功能
    RC与RS唯一区别就是Label Selector支持不同,RS支持新的基于集合的标签,RC仅支持基于等式标签

  • Deployment
    是更高层次的PAI对象,它管理Replica和Pod,并提供声明式更新等功能
    官方建议使用Deployment管理ReplicaSet ,而不是直接使用RelicaSet,这就意味着可能永远不需要直接操作ReplicaSet对象

  • Job
    一次性任务,运行完成后Pod销毁。不再重新启动部署新容器,还可以任务定时运行

  • StatefulSet
    适合持久性的应用程序,有唯一的网络标识符(IP),持久存储,有序的部署、扩展、删除和滚动更新

  • DaementSet
    DaementSet确保所有(或一些)节点运行同一个Pod,当节点加入kubernets集群中,Pod会调到该节点上运行。当节点集群中移除,DaementSet的Pod会被删除,删除DaemonSet会清理它所有创建的Pod

Kubernetes 安装

虚拟机安装centos

  • k8s matser: 2核cpu 系统 cenots 7.9 硬盘20g 内存2048m ip:192.168.31.59 docker版本:18.09.7
  • k8s node :2核cpu 系统 cenots 7.9 硬盘20g 内存2048m ip:192.168.31.181 docker版本:18.09.7

k8s master 安装k8s 2.15版本

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#Kubernetes 安装部署

#Kubernetes --master
# ipaddr 确认主机ip
# 在 master 节点和 worker 节点都要执行
cat /etc/redhat-release
# 此处 hostname 的输出将会是该机器在 Kubernetes 集群中的节点名字
# 不能使用 localhost 作为节点的名字
hostname

# 请使用 lscpu 命令,核对 CPU 信息
# Architecture: x86_64 本安装文档不支持 arm 架构
# CPU(s): 2 CPU 内核数量不能低于 2
lscpu


## 以下脚本在master执行

# 修改 hostname
hostnamectl set-hostname k8s-master
# 查看修改结果
hostnamectl status
# 设置 hostname 解析
echo "127.0.0.1 $(hostname)" >> /etc/hosts
cat /etc/hosts


##安装docker:
##卸载旧版本
yum remove -y docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine

##设置yum docker repository
yum install -y yum-utils device-mapper-persistent-data lvm2

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

##安装并启动 docker
yum install -y docker-ce-18.09.7 docker-ce-cli-18.09.7 containerd.io
systemctl enable docker
systemctl start docker

# 查看docker版本
docker version


# 安装 nfs-utils
yum install -y nfs-utils


#配置K8S的yum源

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

#关闭 防火墙、SeLinux、swap

systemctl stop firewalld
systemctl disable firewalld

setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

swapoff -a
yes | cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab



#修改 /etc/sysctl.conf


vi /etc/sysctl.conf
## 添加以下内容
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1


# 令以上内容执行生效
sysctl -p

## 安装kubelet、kubeadm、kubectl
yum install -y kubelet-1.15.1 kubeadm-1.15.1 kubectl-1.15.1

## 修改docker Cgroup Driver为systemd
vi /usr/lib/systemd/system/docker.service
## 在ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock添加
--exec-opt native.cgroupdriver=systemd

##设置 docker 镜像
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://hrei34jl.mirror.aliyuncs.com"]
}
EOF
# 重启 docker,并启动 kubelet
systemctl daemon-reload
systemctl restart docker
systemctl enable kubelet && systemctl start kubelet

## 初始化 master 节点 需要换成物理网络ip
# 配置 apiserver.demo 的域名
echo "192.168.31.59 apiserver.demo" >> /etc/hosts

##创建 ./kubeadm-config.yaml
cat <<EOF > ./kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.15.1
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
controlPlaneEndpoint: "apiserver.demo:6443"
networking:
podSubnet: "10.100.0.1/20"
EOF

## 初始化 apiserver 根据您服务器网速的情况,您需要等候 1 - 10 分钟
kubeadm init --config=kubeadm-config.yaml --upload-certs

rm -rf /root/.kube/
mkdir /root/.kube/
cp -i /etc/kubernetes/admin.conf /root/.kube/config




##安装 calico

kubectl apply -f https://docs.projectcalico.org/v3.6/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
##等待calico安装就绪:
# 可在 master 节点执行 执行如下命令,等待 3-10 分钟,直到所有的容器组处于 Running 状态
watch kubectl get pod -n kube-system

# 检查 master 初始化结果
kubectl get nodes

安装成功:

kubectl get pod -n kube-system

k8s node 安装k8s 2.15版本

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

##以下脚本在node节点执行

# 在 master 节点和 worker 节点都要执行
cat /etc/redhat-release
# 此处 hostname 的输出将会是该机器在 Kubernetes 集群中的节点名字
# 不能使用 localhost 作为节点的名字
hostname

# 请使用 lscpu 命令,核对 CPU 信息
# Architecture: x86_64 本安装文档不支持 arm 架构
# CPU(s): 2 CPU 内核数量不能低于 2
lscpu
# 修改 hostname
hostnamectl set-hostname k8s-node
# 查看修改结果
hostnamectl status
# 设置 hostname 解析
echo "127.0.0.1 $(hostname)" >> /etc/hosts
cat /etc/hosts

##安装docker:
##卸载旧版本
yum remove -y docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine

##设置yum docker repository
yum install -y yum-utils device-mapper-persistent-data lvm2

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

##安装并启动 docker
yum install -y docker-ce-18.09.7 docker-ce-cli-18.09.7 containerd.io
systemctl enable docker
systemctl start docker

# 查看docker版本
docker version


# 安装 nfs-utils
yum install -y nfs-utils
#配置K8S的yum源

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

#关闭 防火墙、SeLinux、swap

systemctl stop firewalld
systemctl disable firewalld

setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

swapoff -a
yes | cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab

#修改 /etc/sysctl.conf


vi /etc/sysctl.conf
## 添加以下内容
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1


# 令以上内容执行生效
sysctl -p

## 安装kubelet、kubeadm、kubectl
yum install -y kubelet-1.15.1 kubeadm-1.15.1 kubectl-1.15.1

## 修改docker Cgroup Driver为systemd
vi /usr/lib/systemd/system/docker.service
## 在ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock添加
--exec-opt native.cgroupdriver=systemd

##设置 docker 镜像
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://hrei34jl.mirror.aliyuncs.com"]
}
EOF

# 重启 docker,并启动 kubelet
systemctl daemon-reload
systemctl restart docker
systemctl enable kubelet && systemctl start kubelet



##针对所有的 worker 节点执行

# 只在 worker 节点执行 设置masterip
echo "192.168.31.59 apiserver.demo" >> /etc/hosts
# 到k8s master 主机执行获得 join命令参数 待
kubeadm token create --print-join-command

获取到命令复制至k8s node执行: kubeadm join apiserver.demo:6443 --token 1rgjij.n5a0x5mma7v7cylj     --discovery-token-ca-cert-hash sha256:ee62f5d762d73b4dde5abc2dc2ae0dfb69cd0e19ab8587f1b257e60f9aa648d5

可以在k8s master执行:
watch kubectl get pod -n kube-system
kubectl get nodes

node ready:

kubectl get nodes

使用kubectl 访问Kubernetes集群

以下后续kubectl命令在k8s master下执行kubectl

  • kubectl version
    kubectl version

kubectl deploy nginx

  • kubectl run nginx(默认namespace:default)
    1
    kubectl run nginx --image=nginx --replicas=3
    kubectl run nginx
  • 查看pod 列表
    1
    kubectl get pod -o wide -n default

图片/2022/08/22/K8S知/pasted-7.png

  • 查看pod详细信息
    1
    kubectl describe pod  nginx-7bb7cd8db5-kjfm4 -n default
    kubectl describe pod
  • 映射端口
    1
    kubectl expose deployment nginx --port=88 --target-port=80 --type=NodePort -n default
  • 查看service
    1
    kubectl get svc -o wide -n default
    查看service
  • http://192.168.31.59:32125
    访问
  • 查看pod日志
    1
    kubectl log -f  nginx-7bb7cd8db5-kjfm4 -n default

图片/2022/08/22/K8S知/pasted-14.png

  • 删除deploy
    1
    2
    kubectl delete deployment nginx -n default
    kubectl delete svc nginx -n default

kubectl 管理Kubernetes 命令

kubectl 管理Kubernetes 命令1

kubectl 管理Kubernetes 命令2

kubectl 管理Kubernetes 命令3

##部署一个kuboard
kubectl apply -f https://kuboard.cn/install-script/kuboard.yaml

安装Kuboard

Kuboard 是 Kubernetes 的一款图形化管理界面。

https://kuboard.cn/learning/

  • 安装命令

    1
    kubectl apply -f https://kuboard.cn/install-script/kuboard.yaml
  • 执行命令 获取登录token

    1
    kubectl -n kube-system get secret $(kubectl -n kube-system get secret | grep kuboard-user | awk '{print $1}') -o go-template='{{.data.token}}' | base64 -d
  • 访问:http://192.168.31.59:32567/dashboard
    (使用master主机ip 访问32567端口)
    kuboard

  • 使用第二步获取token进行登录

kuboard界面

YAML文件部署(滚动更新 、回滚,弹性伸缩)

  • nginx .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
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: nginx
    spec:
    replicas: 3
    selector:
    matchLabels:
    name: nginx
    template:
    metadata:
    labels:
    name: nginx
    spec:
    containers:
    - name: nginx
    image: nginx:1.15
    imagePullPolicy: Always
    ports:
    - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
    name: nginx-service-nodeport
    spec:
    ports:
    - port: 80
    targetPort: 80
    protocol: TCP
    type: NodePort
    selector:
    name: nginx
  • 在k8s master执行 启动nginx:1.15 ,3个实例
    1
    kubectl apply -f nginx.yaml --record
  • 新开一个终端:
    1
    watch kubectl get pod -o wide  
  • 弹性伸缩
    1
    2
    3
    kubectl scale --replicas=5 deployments/nginx
    kubectl scale --replicas=10 deployments/nginx
    kubectl scale --replicas=2 deployments/nginx
  • 滚动更新
    nginx16 镜像nginx:1.16
    nginx17 镜像nginx:1.17
    1
    2
    kubectl apply -f nginx16.yaml --record
    kubectl apply -f nginx17.yaml --record
  • 列出版本
    1
    kubectl rollout history deployment nginx

列出版本

  • 回滚版本
    1
    kubectl rollout undo deployment nginx --to-revision=2
  • 删除nginx
    1
    kubectl delete -f nginx16.yaml

yaml详解

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
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
100
101
102
apiVersion: extensions/v1beta1   #接口版本
kind: Deployment #接口类型
metadata:
name: cango-demo #Deployment名称
namespace: cango-prd #命名空间
labels:
app: cango-demo #标签
spec:
replicas: 3
strategy:
rollingUpdate: ##由于replicas为3,则整个升级,pod个数在2-4个之间
maxSurge: 1 #滚动升级时会先启动1个pod
maxUnavailable: 1 #滚动升级时允许的最大Unavailable的pod个数
template:
metadata:
labels:
app: cango-demo #模板名称必填
sepc: #定义容器模板,该模板可以包含多个容器
containers:
- name: cango-demo #镜像名称
image: swr.cn-east-2.myhuaweicloud.com/cango-prd/cango-demo:0.0.1-SNAPSHOT #镜像地址
command: [ "/bin/sh","-c","cat /etc/config/path/to/special-key" ] #启动命令
args: #启动参数
- '-storage.local.retention=$(STORAGE_RETENTION)'
- '-storage.local.memory-chunks=$(STORAGE_MEMORY_CHUNKS)'
- '-config.file=/etc/prometheus/prometheus.yml'
- '-alertmanager.url=http://alertmanager:9093/alertmanager'
- '-web.external-url=$(EXTERNAL_URL)'
#如果command和args均没有写,那么用Docker默认的配置。
#如果command写了,但args没有写,那么Docker默认的配置会被忽略而且仅仅执行.yaml文件的command(不带任何参数的)。
#如果command没写,但args写了,那么Docker默认配置的ENTRYPOINT的命令行会被执行,但是调用的参数是.yaml中的args。
#如果如果command和args都写了,那么Docker默认的配置被忽略,使用.yaml的配置。
imagePullPolicy: IfNotPresent #如果不存在则拉取
livenessProbe: #表示container是否处于live状态。如果LivenessProbe失败,LivenessProbe将会通知kubelet对应的container不健康了。随后kubelet将kill掉container,并根据RestarPolicy进行进一步的操作。默认情况下LivenessProbe在第一次检测之前初始化值为Success,如果container没有提供LivenessProbe,则也认为是Success;
httpGet:
path: /health #如果没有心跳检测接口就为/
port: 8080
scheme: HTTP
initialDelaySeconds: 60 ##启动后延时多久开始运行检测
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /health #如果没有心跳检测接口就为/
port: 8080
scheme: HTTP
initialDelaySeconds: 30 ##启动后延时多久开始运行检测
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
resources: ##CPU内存限制
requests:
cpu: 2
memory: 2048Mi
limits:
cpu: 2
memory: 2048Mi
env: ##通过环境变量的方式,直接传递pod=自定义Linux OS环境变量
- name: LOCAL_KEY #本地Key
value: value
- name: CONFIG_MAP_KEY #局策略可使用configMap的配置Key,
valueFrom:
configMapKeyRef:
name: special-config #configmap中找到name为special-config
key: special.type #找到name为special-config里data下的key
ports:
- name: http
containerPort: 8080 #对service暴露端口
volumeMounts: #挂载volumes中定义的磁盘
- name: log-cache
mount: /tmp/log
- name: sdb #普通用法,该卷跟随容器销毁,挂载一个目录
mountPath: /data/media
- name: nfs-client-root #直接挂载硬盘方法,如挂载下面的nfs目录到/mnt/nfs
mountPath: /mnt/nfs
- name: example-volume-config #高级用法第1种,将ConfigMap的log-script,backup-script分别挂载到/etc/config目录下的一个相对路径path/to/...下,如果存在同名文件,直接覆盖。
mountPath: /etc/config
- name: rbd-pvc #高级用法第2中,挂载PVC(PresistentVolumeClaim)

#使用volume将ConfigMap作为文件或目录直接挂载,其中每一个key-value键值对都会生成一个文件,key为文件名,value为内容,
volumes: # 定义磁盘给上面volumeMounts挂载
- name: log-cache
emptyDir: {}
- name: sdb #挂载宿主机上面的目录
hostPath:
path: /any/path/it/will/be/replaced
- name: example-volume-config # 供ConfigMap文件内容到指定路径使用
configMap:
name: example-volume-config #ConfigMap中名称
items:
- key: log-script #ConfigMap中的Key
path: path/to/log-script #指定目录下的一个相对路径path/to/log-script
- key: backup-script #ConfigMap中的Key
path: path/to/backup-script #指定目录下的一个相对路径path/to/backup-script
- name: nfs-client-root #供挂载NFS存储类型
nfs:
server: 10.42.0.55 #NFS服务器地址
path: /opt/public #showmount -e 看一下路径
- name: rbd-pvc #挂载PVC磁盘
persistentVolumeClaim:
claimName: rbd-pvc1 #挂载已经申请的pvc磁盘

Service 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
apiVersion: v1
kind: Service
matadata: #元数据
name: string #service的名称
namespace: string #命名空间
labels: #自定义标签属性列表
- name: string
annotations: #自定义注解属性列表
- name: string
spec: #详细描述
selector: [] #label selector配置,将选择具有label标签的Pod作为管理
#范围
type: string #service的类型,指定service的访问方式,默认为
#clusterIp
clusterIP: string #虚拟服务地址
sessionAffinity: string #是否支持session
ports: #service需要暴露的端口列表
- name: string #端口名称
protocol: string #端口协议,支持TCP和UDP,默认TCP
port: int #服务监听的端口号
targetPort: int #需要转发到后端Pod的端口号
nodePort: int #当type = NodePort时,指定映射到物理机的端口号
status: #当spce.type=LoadBalancer时,设置外部负载均衡器的地址
loadBalancer: #外部负载均衡器
ingress: #外部负载均衡器
ip: string #外部负载均衡器的Ip地址值
hostname: string #外部负载均衡器的主机名

pv.yaml

1

pvc.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-pvc
namespace: nginx
spec:
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 20Gi
storageClassName: nginx-pv

namespace.yaml

1
2
3
4
5
6
kind: Namespace  --创建命名空间
apiVersion: v1
metadata:
 name: nginx --名称
 labels:
name: nginx

ingress.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-yaohong1
namespace: kuboard
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: test.nginx1.com
http:
paths:
- path: /
backend:
serviceName: nginx-service
servicePort: 80
- host: test.kuboard.com
http:
paths:
- path: /
backend:
serviceName: kuboard
servicePort: 80

Pod 和 Sevice联系

  • Kubernetes 中 Pod 是随时可以消亡的(节点故障、容器内应用程序错误等原因)。如果使用 Deployment 运行您的应用程序,Deployment 将会在 Pod 消亡后再创建一个新的 Pod 以维持所需要的副本数。每一个 Pod 有自己的 IP 地址,然而,对于 Deployment 而言,对应 Pod 集合是动态变化的。
    这个现象导致了如下问题:
    • 如果某些 Pod(假设是 ‘backends’)为另外一些 Pod(假设是 ‘frontends’)提供接口,在 ‘backends’ 中的 Pod 集合不断变化(IP 地址也跟着变化)的情况下,
    • ‘frontends’ 中的 Pod 如何才能知道应该将请求发送到哪个 IP 地址?

Service 存在的意义,就是为了解决这个问题。

Kubernetes Service

Kubernetes 中 Service 是一个 API 对象,通过 kubectl + YAML 或者 Kuboard,定义一个 Service,可以将符合 Service 指定条件的 Pod 作为可通过网络访问的服务提供给服务调用者。
Service 是 Kubernetes 中的一种服务发现机制:
* Pod 有自己的 IP 地址
* Service 被赋予一个唯一的 dns name
* Service 通过 label selector 选定一组 Pod
* Service 实现负载均衡,可将请求均衡分发到选定这一组 Pod 中

例如,假设有一个无状态的图像处理后端程序运行了 3 个 Pod 副本。这些副本是相互可替代的(前端程序调用其中任何一个都可以)。在后端程序的副本集中的 Pod 经常变化(销毁、重建、扩容、缩容等)的情况下,前端程序不应该关注这些变化。

服务图

service网络–NodePort

(1)通过设置nodePort映射到物理机,同时设置Service的类型为NodePort:

NodePort

yaml配置

通过Loadbalance将服务暴露出来

LoadBalancer 服务是暴露服务到 internet 的标准方式。在 GKE 上,这种方式会启动一个 Network Load Balancer[2],它将给你一个单独的 IP 地址,转发所有流量到你的服务。

Loadbalance
这个方式的最大缺点是每一个用 LoadBalancer 暴露的服务都会有它自己的 IP 地址,每个用到的 LoadBalancer 都需要付费,这将是非常昂贵的。

通过Ingress暴露服务

为什么使用Ingress,一个重要的原因是LoadBalancer服务都需要创建自己的负载均衡器,以及独有的公有Ip地址,而Ingress只需要一个公网Ip就能为许多服务提供访问。
Ingress
Ingress 事实上不是一种服务类型。相反,它处于多个服务的前端,扮演着“智能路由”或者集群入口的角色。 你可以用 Ingress 来做许多不同的事情,各种不同类型的 Ingress 控制器也有不同的能力。

Ingress2

了解Ingress的工作原理

  • 1)ingress是kubernetes的一个资源对象,用于编写定义规则。

  • 2)反向代理负载均衡器,通常以Service的Port方式运行,接收并按照ingress定义的规则进行转发,通常为nginx,haproxy,traefik等,本次使用nginx。

  • 3)ingress-controller,监听apiserver,获取服务新增,删除等变化,并结合ingress规则动态更新到反向代理负载均衡器上,并重载配置使其生效。

Ingress的工作原理

  • 1.ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化,
  • 2.然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置,
  • 3.再写到nginx-ingress-control的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中,
  • 4.然后reload一下使配置生效。以此达到域名分配置和动态更新的问题。

Ingress 可以解决什么问题

  • 1.动态配置服务
      如果按照传统方式, 当新增加一个服务时, 我们可能需要在流量入口加一个反向代理指向我们新的k8s服务. 而如果用了Ingress, 只需要配置好这个服务, 当服务启动时, 会自动注册到Ingress的中, 不需要而外的操作.

  • 2.减少不必要的端口暴露
      配置过k8s的都清楚, 第一步是要关闭防火墙的, 主要原因是k8s的很多服务会以NodePort方式映射出去, 这样就相当于给宿主机打了很多孔, 既不安全也不优雅. 而Ingress可以避免这个问题, 除了Ingress自身服务可能需要映射出去, 其他服务都不要用NodePort方式

通过相同的Ingress暴露多少服务

  • 1.将不同的服务映射到相同的主机不同的路径
  • 2 将不同的服务映射到不同的主机上

安装Ingress

包含文件

  • 运行ingress-nginx
    1
    kubectl apply -f mandatory.yaml
  • 配置ingress-nginx-svc.yaml 修改externalIPS ip 为k8s master 和k8s node节点ip

ingress-nginx-svc.yaml

1
kubectl apply -f ingress-nginx.svc.yaml
  • 以下命令运行nginx 和kuboard镜像–目的测试ingress
    创建kuboard 命名空间

    1
    kubectl apply -f kuboard-namespace.yaml
  • 创建nginx

    1
    kubectl  apply -f nginx.yaml
  • 创建kuboard

    1
    kubectl apply -f kuboard.yaml
  • 获取token

    1
    2
    kubectl -n kuboard get secret $(kubectl -n kuboard get secret | grep kuboard-user | awk '{print $1}') -o go-template='{{.data.token}}' | base64 -d

  • host文件设置

    1
    192.168.31.59 apiserver.demo test.nginx.com  test.kuboard.com test.nginx1.com test.nginx2.com
  • 配置http://test.nginx.com/ 访问nginx
    kubectl apply -f ingress.yml

test.nginx.com

test.kuboard.com

test.nginx2.com/nginx

仅是模拟不同域名下不同路径 映射不同pod,正常访问kuboard 需要访问test.kuboard.com
http://test.nginx2.com/kuboard

  • 获取ingress
    1
    kubectl get ingress --all-namespaces
  • 删除
    1
    2
    3
    4
    5
    6
    7
    kubectl delete -f nginx.yaml

    kubectl delete -f kuboard.yaml
    kubectl delete -f ingress.yml
    kubectl delete -f ingress1.yml
    kubectl delete -f ingress2.yml
    kubectl delete -f kuboard-namespace.yaml

k8s-dns

前面我们给大家讲解了 Service 的用法,我们可以通过 Service 生成的 ClusterIP(VIP)来访问 Pod 提供的服务,但是在使用的时候还有一个问题:我们怎么知道某个应用的 VIP 呢?比如我们有两个应用,一个是 api 应用,一个是 db 应用,两个应用都是通过 Deployment 进行管理的,并且都通过 Service 暴露出了端口提供服务。api 需要连接到 db 这个应用,我们只知道 db 应用的名称和 db 对应的 Service 的名称,但是并不知道它的 VIP 地址,我们前面的 Service 课程中是不是学习到我们通过 ClusterIP 就可以访问到后面的 Pod 服务,如果我们知道了 VIP 的地址是不是就行了?

那就是可以直接使用 Service 的名称,因为 Service 的名称不会变化,我们不需要去关心分配的 ClusterIP 的地址,因为这个地址并不是固定不变的,所以如果我们直接使用 Service 的名字,然后对应的 ClusterIP 地址的转换能够自动完成就很好了。我们知道名字和 IP 直接的转换是不是和我们平时访问的网站非常类似啊?他们之间的转换功能通过 DNS 就可以解决了,同样的,Kubernetes 也提供了 DNS 的方案来解决上面的服务发现的问题。
DNS 服务不是一个独立的系统服务,而是作为一种 addon 插件而存在,也就是说不是 Kubernetes 集群必须安装的,当然我们强烈推荐安装,可以将这个插件看成是一种运行在 Kubernetes 集群上的一直比较特殊的应用,现在比较推荐的两个插件:kube-dns 和 CoreDNS。

1
kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide

core dns

PV和PVC

* 管理存储是管理计算的一个明显问题。该PersistentVolume子系统为用户和管理员提供了一个API,用于抽象如何根据消费方式提供存储的详细信息。为此,我们引入了两个新的API资源:PersistentVolume和PersistentVolumeClaim

*  PersistentVolume(PV)是集群中由管理员配置的一段网络存储。 它是集群中的资源,就像节点是集群资源一样。 PV是容量插件,如Volumes,但其生命周期独立于使用PV的任何单个pod。 此API对象捕获存储实现的详细信息,包括NFS,iSCSI或特定于云提供程序的存储系统。

  PersistentVolumeClaim(PVC)是由用户进行存储的请求。 它类似于pod。 Pod消耗节点资源,PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式
访问模式:

  • ReadWriteOnce – the volume can be mounted as read-write by a single node
  • ReadOnlyMany – the volume can be mounted read-only by many nodes
  • ReadWriteMany – the volume can be mounted as read-write by many nodes

*  虽然PersistentVolumeClaims允许用户使用抽象存储资源,但是PersistentVolumes对于不同的问题,用户通常需要具有不同属性(例如性能)。群集管理员需要能够提供各种PersistentVolumes不同的方式,而不仅仅是大小和访问模式,而不会让用户了解这些卷的实现方式。对于这些需求,有StorageClass 资源。
*  StorageClass为管理员提供了一种描述他们提供的存储的“类”的方法。 不同的类可能映射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。 Kubernetes本身对于什么类别代表是不言而喻的。 这个概念有时在其他存储系统中称为“配置文件”。
*  PVC和PV是一一对应的。

(生命周期)Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling

  • 供应准备Provisioning—通过集群外的存储系统或者云平台来提供存储持久化支持。
  • 静态提供Static:集群管理员创建多个PV。 它们携带可供集群用户使用的真实存储的详细信息。 它们存在于Kubernetes API中,可用于消费
  • 动态提供Dynamic:当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,集群可能会尝试为PVC动态配置卷。 此配置基于StorageClasses:PVC必须请求一个类,并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用动态配置。
  • 绑定Bound—用户创建pvc并指定需要的资源和访问模式。在找到可用pv之前,pvc会保持未绑定状态。
  • 使用Using—用户可在pod中像volume一样使用pvc。
  • 释放Releasing—用户删除pvc来回收存储资源,pv将变成“released”状态。由于还保留着之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他pvc使用。
  • 回收Recycling—pv可以设置三种回收策略:保留(Retain),回收(Recycle)和删除(Delete)。
  • 保留策略:允许人工处理保留的数据。
  • 删除策略:将删除pv和外部关联的存储资源,需要插件支持。
  • 回收策略:将执行清除操作,之后可以被新的pvc使用,需要插件支持。
  • 注:目前只有NFS和HostPath类型卷支持回收策略,AWS EBS,GCE PD,Azure Disk和Cinder支持删除(Delete)策略。

PV和PVC–以NFS为例子

NFS(Network File System)即网络文件系统,它允许网络中的计算机之间通过TCP/IP网络共享资源。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。

  • 安装nfs-utils master node
    1
    2
    3
    yum install -y nfs-utils  rpcbind
    systemctl start rpcbind nfs
    systemctl enable rpcbind nfs
  • k8s主机设置nfs 共享
    1
    2
    3
    mkdir -p /pv/nginx
    cd /pv/nginx
    vi index.html
  • index.html内容
    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
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
    body {
    width: 35em;
    margin: 0 auto;
    font-family: Tahoma, Verdana, Arial, sans-serif;
    }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>

    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>

    <p><em>Thank you for using nginx.!!!!</em></p>
    </body>
    </html>
  • 设置共享盘 修改masterip
    1
    vi /etc/exports
  • 添加以下内容 后保存 换一下k8s masterip
    1
    /pv/nginx   192.168.31.59/24(rw,sync)
  • 执行exportfs -arv
    1
    exportfs -arv
  • k8s master node执行 换一下k8s masterip
    1
    showmount -e 192.168.31.59
  • 下载pv.zip ,解压后上传至k8s master

pv 文件

  • 创建nginx命名空间
    1
    kubectl apply -f nginx-namespace.yaml
  • 查看命名空间
    1
    kubectl get ns
  • 创建pv 记得修改masterip
    1
    kubectl apply -f nginxpv.yaml

nginx pv

  • 查看pv
    1
    kubectl get pv -n nginx
  • 创建pvc
    1
    kubectl apply -f nginxpvc.yaml
  • 查看pvc
    1
    kubectl get pvc -n nginx
  • 运行nginx
    1
    kubectl apply -f nginx.yaml
  • 查看pod
    1
    kubectl get pod -n nginx
  • 查看svc
    1
    kubectl get svc -n nginx
  • 查看ingress 信息
    1
    kubectl get ingress -n nginx
  • 设置主机名:192.168.31.59 test.nginxpv.com
  • 浏览器访问:http://test.nginxpv.com/

test.nginxpv.com

  • 删除
    1
    kubectl delete -f nginx.yaml

helm

我们在 k8s 中部署一个应用,通常面临以下几个问题:

  • 如何统一管理、配置和更新这些分散的 k8s 的应用资源文件
  • 如何分发和复用一套应用模板
  • 如何将应用的一系列资源当做一个软件包管理

Helm 管理 k8s集群

Helm 可以理解为 Kubernetes 的包管理工具,可以方便地发现、共享和使用为Kubernetes构建的应用。
Helm 采用客户端/服务器架构,有如下组件组成:

helm
Helm CLI 是 Helm 客户端,可以在本地执行

Tiller 是服务器端组件,在 Kubernetes 群集上运行,并管理 Kubernetes 应用程序的生命周期

Repository 是 Chart 仓库,Helm客户端通过HTTP协议来访问仓库中Chart的索引文件和压缩包。

chart Helm的打包格式叫做chart,所谓chart就是一系列文件, 它描述了一组相关的 k8s 集群资源

release 使用 helm install 命令在 Kubernetes 集群中部署的 Chart 称为 Release

mac安装

  • k8s master主机下
    1
    kubectl create serviceaccount --namespace kube-system tiller
    1
    kubectl create clusterrolebinding default-view --clusterrole=cluster-admin --serviceaccount=default:default
    1
    kubectl create clusterrolebinding tiller-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:tiller

kubectl tiller

helm init

  • 成功后 查看helm 版本
    1
    helm version

helm version

helm chart 的基本结构

  • helm create nginxhelm
    1
    helm create nginxhelm

nginxhelm 目录

charts 目录存放依赖的chart

Chart.yaml 包含Chart的基本信息,包括chart版本,名称等

templates 目录下存放应用一系列 k8s 资源的 yaml 模板
_helpers.tpl 此文件中定义一些可重用的模板片断,此文件中的定义在任何资源定义模板中可用

NOTES.txt 介绍chart 部署后的帮助信息,如何使用chart等

values.yaml 包含了必要的值定义(默认值), 用于存储

templates 目录中模板文件中用到变量的值

helm 部署

  • 检查 语法
    1
    helm lint nginxhelm/ 
    helm lint nginxhelm
  • 打包:
    1
    helm package nginxhelm --debug
  • 部署
    1
    helm install nginxhelm --name nginxhelm

helm install

访问

helm(升级 和回退)

  • 修改:Chart.yaml version 0.2.1–>0.2.2
    Chart.yaml

  • 打包:

    1
    helm package nginxhelm --debug
  • 查看版本信息:

    1
    helm search nginxhelm -l
  • 升级

    1
    helm upgrade nginxhelm nginxhelm 

    (helmproject项目有什么更改都可以通过upgrade进行更新k8s)

  • 查看已经升级到最新版本

    1
    helm list

 helm list

  • 回退:
    1
    helm rollback nginxhelm 1

helm rollback 后查看helm list

  • 删除
    1
    helm delete --purge nginxhelm 

helm 常用命令

图片/2022/08/22/K8S知/pasted-42.png

推荐阅读