k8s 实战

滴滴滴--你不是爱拖延,而是爱逃避 / 2024-10-22 / 原文

typora-root-url: ./

⼀:基础集群环境搭建:

k8s基础集群环境主要是运⾏kubernetes管理端服务以及node节点上的服务部署及使⽤

Kubernetes设计架构:

 

CNCF 云原⽣容器⽣态系统概要:

 

1.1  k8s⾼可⽤集群环境规划信息:                                            

安装实际需求,进⾏规划与部署相应的单master或者多master的⾼可⽤k8s运⾏环境。

1.1.1:单master:

kubeadm 安装k8s

 


1.1.2:多master:

 

1.1.3:服务器统计:

 

类型

服务器IP地址

备注

Ansible(2台)

192.168.7.101/102

K8S集群部署服务器,可以和在⼀起

K8S Master(2台)

192.168.7.101/102

K8s控制端,通过⼀个VIP做主备⾼可⽤

Harbor(2台)

192.168.7.103/104

⾼可⽤镜像服务器

Etcd(最少3台)

192.168.7.105/106/107

保存k8s集群数据的服务器

Hproxy(2台)

192.168.7.108/109

⾼可⽤etcd代理服务器

Node节点(2-N台)

192.168.7.111/112/xxx

真正运⾏容器的服务器,⾼可⽤环境⾄少两台

 

 

1.2:主机名设置:


类型

服务器IP

主机名

VIP

K8S Master1

192.168.7.101

k8s-master1.magedu.net

192.168.7.248

K8S Master2

192.168.7.102

k8s-master2.magedu.net

192.168.7.248

Harbor1

192.168.7.103

k8s-harbor1.magedu.net

 

Harbor2

192.168.7.104

k8s-harbor2.magedu.net

 

etcd节点1

192.168.7.105

k8s-etcd1.magedu.net

 

etcd节点2

192.168.7.106

k8s-etcd2.magedu.net

 

etcd节点3

192.168.7.107

k8s-etcd3.magedu.net

 

Haproxy1

192.168.7.108

k8s-ha1.magedu.net

 

Haproxy2

192.168.7.109

k8s-ha2.magedu.net

 

Node节点1

192.168.7.110

k8s-node1.magedu.net

 

Node节点2

192.168.7.111

k8s-node2.magedu.net

 

1.3:软件清单:

当前⽬录下  kubernetes软件清单

API端⼝:

 

 

 

1.4:基础环境准备:

http://releases.ubuntu.com/

统主机名配置、  IP配置、系统参数优化,以及依赖的负载均衡和Harbor部署

1.4.1 :系统配置:

主机名等系统配置略

 

 

1.4.2:⾼可⽤负载均衡:

k8s⾼可⽤反向代理

参⻅博客http://blogs.studylinux.net/?p=4579


1.4.2.1 :keepalived:

 

root@k8s-ha1:~# cat /etc/keepalived/keepalived.conf

vrrp_instance VI_1 {

state MASTER

interface eth0

virtual_router_id 1

priority 100

advert_int 3

unicast_src_ip 192.168.7.108

unicast_peer {

192.168.7.109

}

 

authentication {

auth_type PASS

auth_pass 123abc

}

virtual_ipaddress {

192.168.7.248 dev eth0 label eth0:1

}

}

1.4.2.2 :haproxy:

 

 

 

1.4.3:  Harbor之https:

内部镜像将统⼀保存在内部Harbor服务器,不再通过互联⽹在线下载。

1.4.3.1 :安装harbor:

 


 

#⽣成私有key

root@k8s-harbor1:/apps/harbor/certs# openssl genrsa -out harbor-ca.key

Generating RSA private key, 2048 bit long modulus (2 primes)

......+++++

..............................................................+++++

e is 65537 (0x010001)

#签发证书

root@k8s-harbor1:/apps/harbor/certs# openssl req -x509 -new -nodes -key harbor-ca.key

-subj "/CN=harbor.magedu.net" -days 7120 -out harbor-ca.crt

#修改harbor配置⽂件

root@k8s-harbor1:/apps/harbor/certs# cd ..

root@k8s-harbor1:/apps/harbor# vim harbor.yml

root@k8s-harbor1:/apps/harbor# grep -v "#" harbor.yml | grep -v "^$"

hostname: harbor.magedu.net

http:

port: 80

https:

port: 443

certificate: /apps/harbor/certs/harbor-ca.crt

private_key: /apps/harbor/certs/harbor-ca.key

harbor_admin_password: 123456

database:

password: root123

max_idle_conns: 100

max_open_conns: 900

data_volume: /data

 

root@k8s-harbor1:/apps/harbor# ./install.sh  --with-trivy

 

1.4.3.2 :客户端 同步在crt证书:

 

#同步证书

root@k8s-harbor2:~# mkdir   /etc/docker/certs.d/harbor.magedu.net -p

root@k8s-harbor1:/usr/local/src# scp /apps/harbor/certs/harbor-ca.crt

172.31.7.105:/etc/docker/certs.d/harbor.magedu.net

#添加host⽂件解析

root@k8s-harbor2:~# vim /etc/hosts

172.31.7.104 harbor.magedu.net

#重启docker

root@k8s-harbor2:~# systemctl  restart docker

 


 

1.4.3.3 :测试登录harbor:

 

1.4.3.4 :测试push镜像到harbor:

 

 

 

1.5:⼿动⼆进制部署:

⻅  k8s 1.11 ubuntu1804部署⽂档

 

 

 

1.6 ansible部署:                                                                    

1.6.1 :基础环境准备:

 


 

 

192.168.7.102

192.168.7.103

192.168.7.104

192.168.7.105

192.168.7.106

192.168.7.107

192.168.7.108

192.168.7.109

192.168.7.110

192.168.7.111

"

for node in ${IP};do

sshpass -p 123456 ssh-copy-id  ${node}  -o StrictHostKeyChecking=no

if [ $? -eq 0 ];then

echo "${node} 秘钥copy完成"

else

echo "${node} 秘钥copy失败"

fi

done

 

 

#同步docker证书脚本:

#!/bin/bash

⽬标主机列表

IP="

192.168.7.101

192.168.7.102

192.168.7.103

192.168.7.104

192.168.7.105

192.168.7.106

192.168.7.107

192.168.7.108

192.168.7.109

192.168.7.110

192.168.7.111

"

for node in ${IP};do

sshpass -p 123456 ssh-copy-id  ${node}  -o StrictHostKeyChecking=no

if [ $? -eq 0 ];then

echo "${node} 秘钥copy完成"

echo "${node} 秘钥copy完成 ,准备环境初始化 ....."

ssh  ${node}  "mkdir /etc/docker/certs.d/harbor.magedu.net -p"

echo "Harbor 证书⽬录创建成 !"

scp /etc/docker/certs.d/harbor.magedu.net/harbor-ca.crt

${node}:/etc/docker/certs.d/harbor.magedu.net/harbor-ca.crt

echo "Harbor 证书拷⻉成功 !"

scp   /etc/hosts ${node}:/etc/hosts

echo "host ⽂件拷⻉完成"


 

 

 

1.6.2 :clone项目:

 

1.6.3:准备hosts文件:

 


 

#192.168.7.5

 

[kube-node]

192.168.7.110

 

[new-node] # 预留组,后续添加node节点使⽤

#192.168.7.xx

 

# 参数  NEW_INSTALL:yes表示新建,  no表示使⽤已有harbor服务器

# 如果不使⽤域名,可以设置  HARBOR_DOMAIN=""

[harbor]

#192.168.7.8 HARBOR_DOMAIN="harbor.yourdomain.com" NEW_INSTALL=no

# 负载均衡(⽬前已⽀持多于2节点,⼀般2节点就够了) 安装  haproxy+keepalived

[lb]

192.168.7.1 LB_ROLE=backup

192.168.7.2 LB_ROLE=master

 

# 【可选】外部负载均衡,⽤于⾃有环境负载转发  NodePort 暴露的服务等

[ex-lb]

#192.168.7.6 LB_ROLE=backup EX_VIP=192.168.7.250

#192.168.7.7 LB_ROLE=master EX_VIP=192.168.7.250

 

[all:vars]

# ---------集群主要参数---------------

#集群部署模式:  allinone, single-master, multi-master

DEPLOY_MODE=multi-master

#集群主版本号,⽬前⽀持 : v1.8, v1.9, v1.10v1.11, v1.12, v1.13

K8S_VER="v1.13"

 

# 集群  MASTER IP  LB节点VIP地址,为区别与默认apiserver端⼝,设置VIP监听的服务端⼝8443 # 公有云上请使⽤云负载均衡内⽹地址和监听端⼝

MASTER_IP="192.168.7.248"

KUBE_APISERVER="https://{{ MASTER_IP }}:6443"

 

# 集群⽹络插件,⽬前⽀持calico, flannel, kube-router, cilium

CLUSTER_NETWORK="calico"

 

# 务⽹段  (Service CIDR),注意不要与内⽹已有⽹段冲突

SERVICE_CIDR="10.20.0.0/16"

 

# POD ⽹段  (Cluster CIDR),注意不要与内⽹已有⽹段冲

CLUSTER_CIDR="172.31.0.0/16"

 

服务端⼝范围  (NodePort Range)

NODE_PORT_RANGE="20000-60000"

 

# kubernetes 服务  IP (预分配,⼀般是  SERVICE_CIDR 中第⼀个IP)


 

 

 

1.6.4:准备⼆进制⽂件:

 

k8s-master1:/etc/ansible/bin# pwd

/etc/ansible/bin

k8s-master1:/etc/ansible/bin# tar xvf k8s.1-13-5.tar.gz

k8s-master1:/etc/ansible/bin# mv bin/* .

 

 

1.6.4:开始按步骤部署:

通过ansible脚本初始化环境及部署k8s ⾼可⽤集群

1.6.4.1 :环境初始化

 

root@k8s-master1:/etc/ansible# pwd

/etc/ansible

root@k8s-master1:/etc/ansible# ansible-playbook

 

 

01.prepare.yml

1.6.4.2 :部署etcd集群:

可选更改启动脚本路径

 

root@k8s-master1:/etc/ansible# ansible-playbook

02.etcd.yml

各etcd服务器验证etcd服务:


 

 

 

root@k8s-etcd1:~# export NODE_IPS="192.168.7.105 192.168.7.106 192.168.7.107"

root@k8s-etcd1:~# for ip in ${NODE_IPS}; do   ETCDCTL_API=3 /usr/bin/etcdctl   --

--cacert=/etc/kubernetes/ssl/ca.pem   --

--key=/etc/etcd/ssl/etcd-key.pem   endpoint health; done

healthy: successfully committed proposal: took =

 

healthy: successfully committed proposal: took =

 

healthy: successfully committed proposal: took =

1.6.4.3 :部署docker:

可选更改启动脚本路径,但是docker已经提前安装,因此不需要重新执⾏

 

 

 

1.6.4.4 :部署master:

可选更改启动脚本路径

 

 

 

1.6.4.5 :部署node:

node节点必须安装docker

 

root@k8s-master1:/etc/ansible# vim roles/kube-node/defaults/main.yml

# 基础容器镜像

SANDBOX_IMAGE: "harbor.magedu.net/baseimages/pause-amd64:3.1"

 

root@k8s-master1:/etc/ansible# ansible-playbook  05.kube-node.yml

 

 

1.6.4.5 :部署网络服务calico:

可选更改calico服务启动脚本路径,  csr证书信息

 


 

 

 

验证calico:

 

root@k8s-master1:/etc/ansible# calicoctl  node status

Calico process is running.

 

IPv4 BGP status

+---------------+-------------------+-------+----------+-------------+

| PEER ADDRESS  |     PEER TYPE     | STATE |  SINCE   |    INFO     |

+---------------+-------------------+-------+----------+-------------+

| 192.168.7.110 | node-to-node mesh | up    | 14:22:44 | Established |

+---------------+-------------------+-------+----------+-------------+

 

IPv6 BGP status

No IPv6 peers found.

kubectl run net-test1  --image=alpine --replicas=4  sleep 360000  #创建pod测试夸主机⽹络通信是否正常

1.6.4.6 :添加node节点:

 

1.6.4.7 :添加master节点:

注释掉lb,否则⽆法下⼀步


 

 

 

[kube-master]

192.168.7.101

 

[new-master] # 预留组,后续添加master节点使⽤

192.168.7.102

 

root@k8s-master1:/etc/ansible# ansible-playbook  21.addmaster.yml

1.6.4.8 :验证当前状态:

 

root@k8s-master1:/etc/ansible# calicoctl  node status

Calico process is running.

 

IPv4 BGP status

+---------------+-------------------+-------+----------+-------------+

| PEER ADDRESS  |     PEER TYPE     | STATE |  SINCE   |    INFO     |

+---------------+-------------------+-------+----------+-------------+

 

|

192.168.7.110

|

node-to-node mesh

|

up

|

14:22:45

|

Established

|

|

192.168.7.111

|

node-to-node mesh

|

up

|

14:33:24

|

Established

|

|

192.168.7.102

|

node-to-node mesh

|

up

|

14:42:21

|

Established

|

+---------------+-------------------+-------+----------+-------------+

 

IPv6 BGP status

No IPv6 peers found.

 

root@k8s-master1:/etc/ansible# kubectl  get nodes

NAME            STATUS                     ROLES    AGE   VERSION

192.168.7.101   Ready,SchedulingDisabled   master   37m   v1.13.5

192.168.7.102   Ready,SchedulingDisabled   master   41s   v1.13.5

192.168.7.110   Ready                      node     33m   v1.13.5

192.168.7.111   Ready                      node     15m   v1.13.5

 

 

1.7:  k8s应⽤环境:

1.7.1 :dashboard(1.10.1)

部署kubernetes的web管理界⾯dashboard

1.7.1.1 :具体步骤:

 


 

./ui-admin-rbac.yaml

./ui-read-rbac.yaml

# docker load -i kubernetes-dashboard-amd64-v1.10.1.tar.gz

# docker tag gcr.io/google-containers/kubernetes-dashboard-amd64:v1.10.1

harbor.magedu.net/baseimages/kubernetes-dashboard-amd64:v1.10.1

# docker push harbor.magedu.net/baseimages/kubernetes-dashboard-amd64:v1.10.1

2.修改yaml⽂件中的dashboard镜像地址为本地harbor地址

image: harbor.magedu.net/baseimages/kubernetes-dashboard-amd64:v1.10.1

 

3.创建服务

# kubectl  apply -f .

serviceaccount/admin-user created

clusterrolebinding.rbac.authorization.k8s.io/admin-user created

secret/kubernetes-dashboard-certs created

serviceaccount/kubernetes-dashboard created

role.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created

rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created

deployment.apps/kubernetes-dashboard created

service/kubernetes-dashboard created

serviceaccount/dashboard-read-user created

clusterrolebinding.rbac.authorization.k8s.io/dashboard-read-binding created

clusterrole.rbac.authorization.k8s.io/dashboard-read-clusterrole created

clusterrole.rbac.authorization.k8s.io/ui-admin created

rolebinding.rbac.authorization.k8s.io/ui-admin-binding created

clusterrole.rbac.authorization.k8s.io/ui-read created

rolebinding.rbac.authorization.k8s.io/ui-read-binding created

4.验证dashboard启动完成:

# kubectl  get pods -n  kube-system

 

NAME

READY

STATUS

RESTARTS

AGE

calico-kube-controllers-77d9f69cdd-rbml2

1/1

Running

0

25m

calico-node-rk6jk

1/1

Running

1

20m

calico-node-vjn65

1/1

Running

0

25m

calico-node-wmj48

1/1

Running

0

25m

calico-node-wvsxb

1/1

Running

0

5m14s

kubernetes-dashboard-cb96d4fd8-th6nw

1/1

Running

0

37s

 

 


# kubectl  get  svc  -n  kube-system

NAME                   TYPE       CLUSTER-IP

kubernetes-dashboard   NodePort   10.20.32.158

 

 

EXTERNAL-IP

<none>

 

 

PORT(S)

443:27775/TCP

 

 

AGE

79s


# kubectl  cluster-info #查看集群信息

Kubernetes master is running at https://192.168.7.248:6443

kubernetes-dashboard is running at https://192.168.7.248:6443/api/v1/namespaces/kube-

system/services/https:kubernetes-dashboard:/proxy


 

1.7.1.2 :token登录dashboard:

 

1.7.1.3:  Kubeconfig登录

制作Kubeconfig⽂件

 

 

1.7.1.4 :修改iptables为ipvs及调度算法:

https://github.com/kubernetes/kubernetes/tree/master/pkg/proxy/ipvs

IPVS模式在Kubernetes v1.8中引⼊alpha版本,在v1.9中处于beta版本,在v1.11中处于GA(也就是release版本, 国外都是说GA版本)版本,  IPTABLES模式已在v1.1中添加,并成为v1.2之后的默认操作模式,   IPVS和IPTABLES都 基于netfilter   IPVS模式和IPTABLES模式之间的差异如下:

 

修改kubernetes使⽤ipvs:

https://kubernetes.io/zh/blog/2018/07/09/ipvs-based-in-cluster-load-balancing-deep-dive/

root@s6:~# vim /etc/systemd/system/kube-proxy.service

 

 

--proxy-mode=ipvs \

--ipvs-scheduler=sh

 

算法:

rr: round-robin

lc: least connection

dh: destination hashing

sh: source hashing

sed: shortest expected delay

nq: never queue

1.7.1.5 :设置token登录会话保持时间


 

 

 

# vim dashboard/kubernetes-dashboard.yaml

image: 192.168.200.110/baseimages/kubernetes-dashboard-amd64:v1.10.1

ports:

- containerPort: 8443 protocol: TCP

args:

- --auto-generate-certificates

- --token-ttl=43200

# kubectl  apply  -f .

1.7.2  rancher

https://rancher.com/docs/rancher/v1.6/zh/

https://rancher.com/quick-start/

 

导入集群:

 


 

 

 

web页面:

 

 

 

启用监控:

 


 

1.7.3  kuboard

https://kuboard.cn/overview/#kuboard%E5%9C%A8%E7%BA%BF%E4%BD%93%E9%AA%8C

 

 

在浏览器输⼊  http://your-host-ip:80 即可访问  Kuboard v3.x 的界⾯,登录⽅式:

户名:    admin

 码    Kuboard123

 

 

 

 

 

 


 

 

 

 

 

对k8s中的容器和其他资源进⾏管理:

 

 

 

#进⼊容器进⾏单独⽇志查等操作:


 

 

 

 

 

进⼊容器进⾏操作:

 

 

 

1.8:  DNS服务:

⽬前常⽤的dns组件有kube-dns和coredns两个,即到⽬前k8s版本 1.17.X都可以使⽤,  kube-dns和coredns⽤于 解析k8s集群中service name所对应得到IP地址。

1.8.1:部署kube-dns:

k8s 1.18版本后将不再⽀持kube-dns。

.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.18.                             -   

r-v1180

kubeadm: kube-dns is deprecated and will not be supported in a future version

 

 


 

dns-dnsmasq:提供DNS缓存,降低kubedns负载,提⾼性能

dns-sidecar:定期检查kubednsdnsmasq的健康状

2.导⼊镜像并上传⾄本地harbor

# docker load -i k8s-dns-kube-dns-amd64_1.14.13.tar.gz

# docker images

# docker tag gcr.io/google-containers/k8s-dns-kube-dns-amd64:1.14.13

harbor.magedu.net/baseimages/k8s-dns-kube-dns-amd64:1.14.13

# docker push harbor.magedu.net/baseimages/k8s-dns-kube-dns-amd64:1.14.13

 

 

# docker load -i  k8s-dns-sidecar-amd64_1.14.13.tar.gz

# docker images

# docker tag gcr.io/google-containers/k8s-dns-sidecar-amd64:1.14.13

harbor.magedu.net/baseimages/k8s-dns-sidecar-amd64:1.14.13

# docker push harbor.magedu.net/baseimages/k8s-dns-sidecar-amd64:1.14.13

 

# docker load -i k8s-dns-dnsmasq-nanny-amd64_1.14.13.tar.gz

# docker imgaes

# docker images

# docker  tag gcr.io/google-containers/k8s-dns-dnsmasq-nanny-amd64:1.14.13

harbor.magedu.net/baseimages/k8s-dns-dnsmasq-nanny-amd64:1.14.13

# docker push harbor.magedu.net/baseimages/k8s-dns-dnsmasq-nanny-amd64:1.14.13

3.修改yaml⽂件中的镜像地址为本地harbor地址

# vim kube-dns.yaml

- name: kubedns

image: harbor.magedu.net/baseimages/k8s-dns-kube-dns-amd64:1.14.13

 

- name: dnsmasq

image: harbor.magedu.net/baseimages/k8s-dns-dnsmasq-nanny-amd64:1.14.13

 

- name: sidecar

image: harbor.magedu.net/baseimages/k8s-dns-sidecar-amd64:1.14.13

 

 

4.创建服务

# kubectl  apply -f  kube-dns.yaml

1.8.2:部署coredns:

https://github.com/coredns/coredns

coredns 1.2/1.3/1.4/1.5版本:

 


 

1.6版本:

https://github.com/coredns/deployment/tree/master/kubernetes #1.6部署⽅式

 

1.8.3:域名解析测试:

 

 

# kubectl

delete -f /etc/ansible/manifests/dns/kube-dns/kube-dns.yaml #删除kube-dns

# kubectl

apply -f  coredns.yaml  #部署coredns

# kubectl

exec busybox nslookup kubernetes

Server:

10.20.254.254

Address 1:

10.20.254.254 kube-dns.kube-system.svc.linux36.local

Name:

kubernetes

Address 1:

10.20.0.1 kubernetes.default.svc.linux36.local

# kubectl

exec busybox nslookup kubernetes.default.svc.linux36.local

Server:

10.20.254.254

Address 1:

10.20.254.254 kube-dns.kube-system.svc.linux36.local

Name:

kubernetes.default.svc.linux36.local

Address 1:

10.20.0.1 kubernetes.default.svc.linux36.local

#  kubectl

exec busybox nslookup kube-dns.kube-system.svc.magedu.local

Server:

10.10.0.2

Address 1:

10.10.0.2 kube-dns.kube-system.svc.magedu.local

Name:

kube-dns.kube-system.svc.magedu.local

Address 1:

10.10.0.2 kube-dns.kube-system.svc.magedu.local

 

1.8.4:监控组件heapster:

heapster:数据采集

influxdb:数据存储

grafana:web展示

 

⼆:  k8s运⾏机制及术语:                                       


 

分解k8s集群中master 、node 、etcd 、calico和flannel的运⾏机制

2.1:  master运行机制:

master的运⾏机制

2.1.1  kube-apiserver

https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kube-apiserver/

k8s API Server提供了k8s各类资源对象(pod,RC,Service)的增删改查及watch等HTTP Rest接⼝,是整个系统 的数据总线和数据中⼼。

apiserver ⽬前在master监听两个端⼝,通过 --insecure-port int 监听⼀个⾮安全的127.0.0.1本地端⼝(默认为 8080):

 

该端⼝⽤于接收HTTP请求;

该端⼝默认值为8080,可以通过API Server的启动参数“--insecure-port”的值来修改默认值;

默认的IP地址为“localhost”,可以通过启动参数“--insecure-bind-address”的值来修改该IP地址;

⾮认证或未授权的 HTTP请求通过该端⼝访问API Server(kube-controller-managerkube-scheduler)

通过参数--bind-address=192.168.7.101 监听⼀个对外访问且安全(https)的端⼝(默认为6443):

 

该端⼝默认值为6443,可通过启动参数“--secure-port”的值来修改默认值;

默认IP地址为⾮本地(Non-Localhost)⽹络端⼝,通过启动参数“--bind-address”设置该值; 该端⼝⽤于接收客户端、  dashboard等外部HTTPS请求;

⽤于基于Tocken⽂件或客户端证书及HTTP Base的认证;

⽤于基于策略的授权;

kubernetes API Server的功能与使⽤:

 

提供了集群管理的REST API接⼝(包括认证授权、数据校验以及集群状态变更)

提供其他模块之间的数据交互和通信的枢纽(其他模块通过API Server查询或修改数据,只有API Server才直接操 作etcd)  ;

是资源配额控制的⼊⼝;

拥有完备的集群安全机制 .

# curl 127.0.0.1:8080/apis #分组api

# curl 127.0.0.1:8080/api/v1 #带具体版本号的api

# curl  127.0.0.1:8080/  #返回核⼼ api列表

# curl  127.0.0.1:8080/version #api 版本信息

# curl 127.0.0.1:8080/healthz/etcd #与etcd的⼼跳监测

# curl 127.0.0.1:8080/apis/autoscaling/v1 #api的详细信息

# curl  127.0.0.1:8080/metrics #指标数据

启动脚本:

 


 

 

 

[Unit]

Description=Kubernetes API Server

Documentation=https://github.com/GoogleCloudPlatform/kubernetes

After=network.target

 

[Service]

ExecStart=/usr/bin/kube-apiserver \

--admission-

control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota

,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook \

--bind-address=192.168.7.101 \ #外部监听端口

--insecure-bind-address=127.0.0.1 \  #本机监听端口

--authorization-mode=Node,RBAC \

--kubelet-https=true \

--kubelet-client-certificate=/etc/kubernetes/ssl/admin.pem \

--kubelet-client-key=/etc/kubernetes/ssl/admin-key.pem \

--anonymous-auth=false \

--basic-auth-file=/etc/kubernetes/ssl/basic-auth.csv \

--service-cluster-ip-range=10.20.0.0/16 \

--service-node-port-range=30000-60000 \

--tls-cert-file=/etc/kubernetes/ssl/kubernetes.pem \

--tls-private-key-file=/etc/kubernetes/ssl/kubernetes-key.pem \

--client-ca-file=/etc/kubernetes/ssl/ca.pem \

--service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \

--etcd-cafile=/etc/kubernetes/ssl/ca.pem \

--etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem \

--etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem \

--etcd-

servers=https://192.168.7.105:2379,https://192.168.7.106:2379,https://192.168.7.107:237

9 \

--enable-swagger-ui=true \

--endpoint-reconciler-type=lease \

--allow-privileged=true \

--audit-log-maxage=30 \

--audit-log-maxbackup=3 \

--audit-log-maxsize=100 \

--audit-log-path=/var/lib/audit.log \

--event-ttl=1h \

--requestheader-client-ca-file=/etc/kubernetes/ssl/ca.pem \

--requestheader-allowed-names= \

--requestheader-extra-headers-prefix=X-Remote-Extra- \

--requestheader-group-headers=X-Remote-Group \

--requestheader-username-headers=X-Remote-User \

--proxy-client-cert-file=/etc/kubernetes/ssl/aggregator-proxy.pem \

--proxy-client-key-file=/etc/kubernetes/ssl/aggregator-proxy-key.pem \

--enable-aggregator-routing=true \

--runtime-config=batch/v2alpha1=true \

--v=2


 

 

 

2.1.2  kube-controller-manager

Controller Manager作为集群内部的管理控制中⼼,⾮安全默认端⼝10252,负责集群内的Node 、Pod副本、服务 端点(Endpoint)、命名空间(Namespace)、服务账号(ServiceAccount)、资源定额(ResourceQuota)的 管理,当某个Node意外宕机时,  Controller Manager会及时发现并执⾏⾃动化修复流程,确保集群始终处于预期  的⼯作状态。

启动脚本:

 

# vim /etc/systemd/system/kube-controller-manager.service

 

[Unit]

Description=Kubernetes Controller Manager

Documentation=https://github.com/GoogleCloudPlatform/kubernetes

 

[Service]

ExecStart=/usr/bin/kube-controller-manager \

--address=127.0.0.1 \

--master=http://127.0.0.1:8080 \ #调⽤ kube-api-server的本地端⼝进⾏通信

--allocate-node-cidrs=true \

--service-cluster-ip-range=10.20.0.0/16 \

--cluster-cidr=172.31.0.0/16 \

--cluster-name=kubernetes \

--cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \

--cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \

--service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \

--root-ca-file=/etc/kubernetes/ssl/ca.pem \

--horizontal-pod-autoscaler-use-rest-clients=true \

--leader-elect=true \

--v=2

Restart=on-failure

RestartSec=5

 

[Install]

WantedBy=multi-user.target

 


 

2.1.3  kube-scheduler

Scheduler负责Pod调度,在整个系统中起"承上启下"作⽤,承上:负责接收Controller Manager创建的新的Pod, 为其选择⼀个合适的Node;启下:  Node上的kubelet接管Pod的⽣命周期。

启动脚本:

 

# vim /etc/systemd/system/kube-scheduler.service

 

[Unit]

Description=Kubernetes Scheduler

Documentation=https://github.com/GoogleCloudPlatform/kubernetes

 

[Service]

ExecStart=/usr/bin/kube-scheduler \

--address=127.0.0.1 \

--master=http://127.0.0.1:8080 \ #调⽤ kube-api-server的本地端⼝进⾏通信

--leader-elect=true \

--v=2

Restart=on-failure

RestartSec=5

 

[Install]

WantedBy=multi-user.target

 

 

 

 

通过调度算法为待调度Pod列表的每个Pod从可⽤Node列表中选择⼀个最适合的Node,并将信息写⼊etcd中

node节点上的kubelet通过API Server监听到kubernetes Scheduler产⽣的Pod绑定信息,然后获取对应的Pod 清单,下载Image,并启动容器。

优选策略

1.LeastRequestedPriority

先从备选节点列表中选择资源消耗最⼩的节点(CPU+内存)。

2.CalculateNodeLabelPriority

优先选择含有指定Label的节点。

3.BalancedResourceAllocation

优先从备选节点列表中选择各项资源使⽤率最均衡的节点。

图⽚:


 

 

 

 

 

2.2:  node节点运行机制:

2.1.2  kubelet

在kubernetes集群中,每个Node节点都会启动kubelet进程,⽤来处理Master节点下发到本节点的任务,管理 Pod和其中的容器。  kubelet会在API Server上注册节点信息,定期向Master汇报节点资源使⽤情况,并通过     cAdvisor(顾问)监控容器和节点资源,可以把kubelet理解成Server/Agent架构中的agent  kubelet是Node上的 pod管家。

https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/#options

启动脚本:

 


 

--anonymous-auth=false \

--authentication-token-webhook \

--authorization-mode=Webhook \

--client-ca-file=/etc/kubernetes/ssl/ca.pem \

--cluster-dns=10.20.254.254 \

--cluster-domain=linux36.local. \

--cni-bin-dir=/usr/bin \

--cni-conf-dir=/etc/cni/net.d \

--fail-swap-on=false \

--hairpin-mode hairpin-veth \

--hostname-override=192.168.7.111 \

--kubeconfig=/etc/kubernetes/kubelet.kubeconfig \  #配置⽂件

--max-pods=110 \

--network-plugin=cni \

--pod-infra-container-image=harbor.magedu.net/baseimages/pause-amd64:3.1 \

--register-node=true \

--root-dir=/var/lib/kubelet \

--tls-cert-file=/etc/kubernetes/ssl/kubelet.pem \

--tls-private-key-file=/etc/kubernetes/ssl/kubelet-key.pem \

--v=2

#kubelet cAdvisor 默认在所有接⼝监听  4194 端⼝的请 , 以下iptables限制内⽹访问                             ExecStartPost=/sbin/iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 4194 -j ACCEPT    ExecStartPost=/sbin/iptables -A INPUT -s 172.16.0.0/12 -p tcp --dport 4194 -j ACCEPT ExecStartPost=/sbin/iptables -A INPUT -s 192.168.0.0/16 -p tcp --dport 4194 -j ACCEPT ExecStartPost=/sbin/iptables -A INPUT -p tcp --dport 4194 -j DROP

Restart=on-failure

RestartSec=5

 

[Install]

WantedBy=multi-user.target

 

 

 

 

PLEG:即Pod Lifecycle Event Generator,pleg会记录Pod⽣命周期中的各种事件 ,如容器的启动、终⽌等。

Container GC:Kubernetes 垃圾回收(Garbage Collection)机制由kubelet完成,  kubelet定期清理不再 使⽤的容器和镜像,每分钟进⾏⼀次容器的GC,每五分钟进⾏⼀次镜像的GC。

Pod Eviction k8s⼀个特⾊功能,它在某些场景下应⽤,如节点NotReadyNode节点资源不⾜,把pod驱逐⾄其

它Node节点。

Kube-controller-manager: 周期性检查所有节点状态,当节点处于NotReady状态超过⼀段时间后,驱逐该 节点上所有  pod。

Kubelet: 周期性检查本节点资源,当资源不⾜时,按照优先级驱逐部分  pod

SyncLoop:控制pod ⽣命周期的循环,驱动整个控制循环的事件有:  pod更新事件、  pod⽣命周期变化、  kubelet

本身设置的执⾏周期、定时清理事件等。

handlepods: kubelet针对pod的处理程序,创建pod、删除pod等。

 


 

 

 

 

 

 


 

2.1.2  kube-proxy

kube-proxy 运⾏在每个节点上,监听 API Server 中服务对象的变化,再通过管理 IPtables或者IPVS规则 来实 络的转发

Kube-Proxy 不同的版本可⽀持三种⼯作模式:                                                                                            https://kubernetes.io/zh/docs/concepts/services-networking/service/ #service介绍                              https://kubernetes.io/zh/blog/2018/07/09/ipvs-based-in-cluster-load-balancing-deep-dive/ #使⽤IPVS

 

UserSpace

k8s v1.2 及以后就已经淘汰

IPtables

⽬前默认⽅式,  1.1开始⽀持,  1.2开始为默认

IPVS

1.9引⼊到1.11正式版本,需要安装ipvsadm、ipset ⼯具包和加载  ip_vs 内核模块

启动脚本:

 

root@k8s-node2:~# cat  /etc/systemd/system/kube-proxy.service

[Unit]

Description=Kubernetes Kube-Proxy Server

Documentation=https://github.com/GoogleCloudPlatform/kubernetes

After=network.target

 

[Service]

WorkingDirectory=/var/lib/kube-proxy

ExecStart=/usr/bin/kube-proxy \

--bind-address=192.168.7.111 \

--hostname-override=192.168.7.111 \

--kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig \ #配置⽂件

--logtostderr=true \

--proxy-mode=iptables #配置转发模式

Restart=on-failure

RestartSec=5

LimitNOFILE=65536

 

[Install]

WantedBy=multi-user.target

2.1.2.1 :iptables:

Kube-Proxy 监听 Kubernetes Master 增加和删除 Service 以及 Endpoint 的消息。对于每⼀个 Service  Kube     Proxy 创建相应的 IPtables 规则,并将发送到 Service Cluster IP 的流量转发到 Service 后端提供服务的 Pod 的相 应端⼝上。

注:

虽然可以通过 Service  Cluster IP 和服务端⼝访问到后端 Pod 提供的服务,但该 Cluster IP  Ping 不通的。 其原因是 Cluster IP 只是 IPtables 中的规则,并不对应到⼀个任何⽹络设备。


 

IPVS 模式的 Cluster IP 是可以 Ping 通的。

 

2.1.2.2:  IPVS:

kubernetes1.9开始测试⽀持ipvs(Graduate kube-proxy IPVS mode to beta)  https://github.com/kubernetes /kubernetes/blob/master/CHANGELOG-1.9.md#ipvs ,从1.11版本正式⽀持ipvs(IPVS-based in-cluster load       balancing is now GA)  https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-                           1.11.md#ipvs

IPVS 相对 IPtables 效率会更⾼⼀些,使⽤ IPVS 模式需要在运⾏ Kube-Proxy 的节点上安装 ipvsadm 、ipset ⼯具 包和加载 ip_vs 内核模块,当 Kube-Proxy  IPVS 代理模式启动时,  Kube-Proxy 将验证节点上是否安装了 IPVS  模块,如果未安装,则 Kube-Proxy 将回退到 IPtables 代理模式。

 

使⽤IPVS模式,  Kube-Proxy会监视Kubernetes Service对象和Endpoints,调⽤宿主机内核Netlink接⼝以相 应地创建IPVS规则并定期与Kubernetes Service对象  Endpoints对象同步IPVS规则,以确保IPVS状态与期望⼀

致,访问服务时,流量将被重定向到其中⼀个后端  Pod,IPVS使⽤哈希表作为底层数据结构并在内核空间中⼯作,这意 味着IPVS可以更快地重定向流量,并且在同步代理规则时具有更好的性能,此外,  IPVS 为负载均衡算法提供了更多选 项,例如:  rr (轮询调度)、lc (最⼩连接数)、dh (⽬标哈希)、sh (源哈希)、sed (最短期望延迟 )、nq(不排队 调度)等。

配置⽅式:

配置使⽤IPVS及指定调度算法:


 

https://kubernetes.io/zh/docs/reference/config-api/kube-proxy-config.v1alpha1/#ClientConnectionConfigur ation

 

# cat  /var/lib/kube-proxy/kube-proxy-config.yaml

kind: KubeProxyConfiguration

apiVersion: kubeproxy.config.k8s.io/v1alpha1

bindAddress: 172.31.7.111

clientConnection:

kubeconfig: "/etc/kubernetes/kube-proxy.kubeconfig"

clusterCIDR: "10.100.0.0/16"

conntrack:

maxPerCore: 32768

min: 131072

tcpCloseWaitTimeout: 1h0m0s

tcpEstablishedTimeout: 24h0m0s

healthzBindAddress: 172.31.7.111:10256

hostnameOverride: "172.31.7.111"

metricsBindAddress: 172.31.7.111:10249

mode: "ipvs"

ipvs:

scheduler: sh

开启service会话保持:

 

kind: Service

apiVersion: v1

metadata:

labels:

app: magedu-nginx-service-label

name: magedu-nginx-service

namespace: magedu

spec:

type: NodePort

ports:

- name: http

port: 80

protocol: TCP

targetPort: 80

nodePort: 30004

selector:

app: nginx

sessionAffinity: ClientIP

sessionAffinityConfig:

clientIP:

timeoutSeconds: 1800

 


 

 

 

 

 

 

2.3 :etcd运行机制:

etcd是CoreOS团队于2013年6⽉发起的开源项⽬,它的⽬标是构建⼀个⾼可⽤的分布式键值(key-value)数据库。 etcd内部采⽤raft协议作为⼀致性算法,  etcd基于Go语⾔实现。

官⽅⽹站:  https://etcd.io/

github地址  https://github.com/etcd-io/etcd

https://etcd.io/docs/v3.4/op-guide/hardware/ #官⽅硬件推荐

 


 

2.3.1 :启动脚本参数:

 

root@k8s-etcd1:~# cat /etc/systemd/system/etcd.service

[Unit]

Description=Etcd Server

After=network.target

After=network-online.target

Wants=network-online.target

Documentation=https://github.com/coreos

 

[Service]

Type=notify

WorkingDirectory=/var/lib/etcd/ #数据保存⽬录

ExecStart=/usr/bin/etcd \ #⼆进制⽂件路径

--name=etcd1 \  #当前node 名称

--cert-file=/etc/etcd/ssl/etcd.pem \

--key-file=/etc/etcd/ssl/etcd-key.pem \

--peer-cert-file=/etc/etcd/ssl/etcd.pem \

--peer-key-file=/etc/etcd/ssl/etcd-key.pem \

--trusted-ca-file=/etc/kubernetes/ssl/ca.pem \

--peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \

--initial-advertise-peer-urls=https://192.168.7.105:2380 \ #通告⾃⼰的集群端⼝ --listen-peer-urls=https://192.168.7.105:2380 \ #集群之间通讯端⼝

--listen-client-urls=https://192.168.7.105:2379,http://127.0.0.1:2379 \ #客户端访问地址 --advertise-client-urls=https://192.168.7.105:2379 \ #通告⾃⼰的客户端端⼝

--initial-cluster-token=etcd-cluster-0 \  #创建集群使⽤的token,⼀个集群内的节点保持⼀致 --initial-

cluster=etcd1=https://192.168.7.105:2380,etcd2=https://192.168.7.106:2380,etcd3=https:/

/192.168.7.107:2380 \  #集群所有的节点信息

--initial-cluster-state=new \ #新建集群的时候的值为new,如果是已经存在的集群为existing --data-dir=/var/lib/etcd #数据⽬录路径

Restart=on-failure

RestartSec=5

LimitNOFILE=65536

 

[Install]

WantedBy=multi-user.target

2.3.2:查看成员信息:

etcd有多个不同的API访问版本,  v1版本已经废弃,  etcd v2 v3 本质上是共享同⼀套 raft 协议代码的两个独⽴的 应⽤,接⼝不⼀样,存储不⼀样,数据互相隔离。也就是说如果从 Etcd v2 升级到 Etcd v3,原来v2 的数据还是只 能⽤ v2 的接⼝访问,  v3 的接⼝创建的数据也只能访问通过 v3 的接⼝访问。

WARNING:

Environment variable ETCDCTL_API is not set; defaults to etcdctl v2. #默认使⽤V2版本                           Set environment variable ETCDCTL_API=3 to use v3 API or ETCDCTL_API=2 to use v2 API. #设置API版本


 

 

 

root@k8s-etcd1:~# ETCDCTL_API=3 etcdctl --help

root@k8s-etcd1:~# ETCDCTL_API=3 etcdctl member --help

NAME:

etcdctl member - member add, remove and list subcommands

 

USAGE:

etcdctl member command [command options] [arguments...]

 

 

enumerate existing cluster members

add a new member to the etcd cluster

remove an existing member from the etcd cluster

update an existing member in the etcd cluster

 

OPTIONS:

--help, -h  show help

2.3.3:验证当前etcd所有成员状态:

验证etcd集群状态

2.3.3.1 :⼼跳信息:

 

root@k8s-etcd1:~# export NODE_IPS="172.31.7.106 172.31.7.107 172.31.7.108"

 

root@k8s-etcd1:~# for ip in ${NODE_IPS}; do   ETCDCTL_API=3 /usr/bin/etcdctl   --

endpoints=https://${ip}:2379    --cacert=/etc/kubernetes/ssl/ca.pem   --

cert=/etc/kubernetes/ssl/etcd.pem   --key=/etc/kubernetes/ssl/etcd-key.pem   endpoint

health; done

 

2.3.3.2 :显示集群成员信息:

 


 

 

 

2.3.3.3 :以表格⽅式显示节点详细状态:

 

root@k8s-etcd1:~# export NODE_IPS="172.31.7.106 172.31.7.107 172.31.7.108"

 

root@k8s-etcd1:~# for ip in ${NODE_IPS}; do   ETCDCTL_API=3 /usr/bin/etcdctl --write-

out=table endpoint status   --endpoints=https://${ip}:2379    --

cacert=/etc/kubernetes/ssl/ca.pem   --cert=/etc/kubernetes/ssl/etcd.pem   --

key=/etc/kubernetes/ssl/etcd-key.pem; done

 

2.3.4:查看etcd数据信息:

查看etcd集群中保存的数据

2.3.4.1 :查看所有key:

 


 

 

 

2.3.4.2 :查看指定的key:

 

 

2.3.4.3 :查看所有calico的数据:

 

root@etcd1:~# ETCDCTL_API=3 etcdctl  get --keys-only --prefix /calico | grep local  #查 看etcd中calico的相关数据

/calico/resources/v3/projectcalico.org/nodes/k8s-master1.magedu.local.priview

/calico/resources/v3/projectcalico.org/nodes/k8s-master2.magedu.local.priview

/calico/resources/v3/projectcalico.org/nodes/k8s-master3.magedu.local.priview

/calico/resources/v3/projectcalico.org/nodes/k8s-node1.magedu.local.priview

/calico/resources/v3/projectcalico.org/nodes/k8s-node2.magedu.local.priview

/calico/resources/v3/projectcalico.org/nodes/k8s-node3.magedu.local.priview

 

 

2.3.5 :etcd增删改查数据:

 


 

 

 

2.3.6 :etcd数据watch机制:

基于不断监看数据,发⽣变化就主动触发通知客户端,  Etcd v3 的watch机制⽀持watch某个固定的key,也⽀持 watch⼀个范围。

相⽐Etcd v2, Etcd v3的⼀些主要变化:

 

接⼝通过grpc提供rpc接⼝,放弃了v2http接⼝,优势是⻓连接效率提升明显,缺点是使⽤不如以前⽅便,尤其对

不⽅便维护⻓连接的场景。

废弃了原来的⽬录结构,变成了纯粹的kv,⽤户可以通过前缀匹配模式模拟⽬录。

内存中不再保存value,同样的内存可以⽀持存储更多的key。

watch机制更稳定,基本上可以通过watch机制实现数据的完全同步。

提供了批量作以及事务机制,⽤户可以通过批量事务请求来实现Etcd v2CAS机制(批量事务⽀持if条件判断)。

watch测试:

 

#在etcd node1上watch⼀个key,没有此key也可以执⾏watch,后期可以再创建:

root@etcd1:~# ETCDCTL_API=3  /usr/bin/etcdctl watch  /name

#在etcd node2修改数据,验证etcd node1是否能够发现数据变化

root@etcd2:~# ETCDCTL_API=3  /usr/bin/etcdctl put  /data "data v1"

OK

root@etcd2:~# ETCDCTL_API=3  /usr/bin/etcdctl put  /data "data v2"

OK

 


 

 

 

 

 

2.3.7 :etcd数据备份与恢复机制:

WAL是writeahead log的缩写,顾名思义,也就是在执⾏真正的写操作之前先写⼀个⽇志,预写⽇志。

wal: 存放预写式⽇志,最⼤的作⽤是记录了整个数据变化的全部历程。在etcd中,所有数据的修改在提交前,都要 先写⼊到WAL中。

2.3.7.1 :etcd v2版本数据备份与恢复:

 

V2版本帮助信息:

root@k8s-etcd2:~# /usr/bin/etcdctl backup --help

NAME:

etcdctl backup - backup an etcd directory

 

USAGE:

etcdctl backup [command options]

 

OPTIONS:

--data-dir value        Path to the etcd data dir #源数据⽬录

--wal-dir value         Path to the etcd wal dir

--backup-dir value      Path to the backup dir #备份⽬录

--backup-wal-dir value  Path to the backup wal dir

 

V2版本备份数据:

root@k8s-etcd2:~# ETCDCTL_API=2 etcdctl backup  --data-dir /var/lib/etcd/ --backup-dir

/opt/etcd_backup

2019-07-11 18:59:57.674432 I | wal: segmented wal file

/opt/etcd_backup/member/wal/0000000000000001-0000000000017183.wal is created

 

V2版本恢复数据:

#恢复帮助信息:

root@k8s-etcd2:~# etcd --help | grep force

--force-new-cluster 'false'

force to create a new one-member cluster.

 

etcd --data-dir=/var/lib/etcd/default.etcd --force-new-cluster &

 

root@k8s-etcd2:~# vim /etc/systemd/system/etcd.service

[Unit]

Description=Etcd Server


 

 

 

2.3.7.2 :etcd 集群v3版本数据⼿动备份与恢复:

 

V3版本备份数据:

root@k8s-etcd2:~# ETCDCTL_API=3 etcdctl  snapshot save  snapshot.db

Snapshot saved at snapshot.db

 

V3版本恢复数据:

root@k8s-etcd2:~#  ETCDCTL_API=3  etcdctl snapshot restore  snapshot.db  --data- dir=/opt/etcd-testdir #将数据恢复到⼀个新的不存在的⽬录中

2019-07-11 18:57:46.526757 I | mvcc: restore compact to 74541

2019-07-11 18:57:46.536114 I | etcdserver/membership: added member 8e9e05c52164694d

[http://localhost:2380] to cluster cdf818194e3a8c32

#⾃动备份数据

root@k8s-etcd2:~# mkdir /data/etcd-backup-dir/ -p

root@k8s-etcd2:~# cat  script.sh

#!/bin/bash

source /etc/profile

DATE=`date +%Y-%m-%d_%H-%M-%S`

ETCDCTL_API=3 /usr/bin/etcdctl  snapshot save  /data/etcd-backup-dir/etcd-snapshot-

${DATE}.db

2.3.7.3 :etcd 集群v3版本数据⾃动备份与恢复:


 

 

 

root@k8s-master1:/etc/kubeasz# ./ezctl backup  k8s-01

 

root@k8s-master1:/etc/kubeasz# kubectl  delete pod net-test4

pod "net-test4" deleted

 

root@k8s-master1:/etc/kubeasz# ./ezctl restore k8s-01

2.3.7.4:  ETCD数据恢复流程:

当etcd集群宕机数量超过集群总节点数⼀半以上的时候(如总数为三台宕机两台),就会导致整合集群宕机,后期需 要重新恢复数据,则恢复流程如下:

 

1、恢复服务器系统

2、重新部署ETCD集群

3、停⽌kube-apiserver/controller-manager/scheduler/kubelet/kube-proxy

4、停⽌ETCD集群

5、各ETCD节点恢复同⼀份备份数据

6、启动各节点并验证ETCD集群

7、启动kube-apiserver/controller-manager/scheduler/kubelet/kube-proxy

8、验证k8s master态及pod数据

2.3.7.5:  ETCD集群节点添加与删除:

节点维护主要是节点的添加或删除

 

 

 

2.4⽹络通信机制                                                                    

k8s中的⽹络主要涉及到pod的的各种访问需求,如同⼀pod的内部(单容器或者多容器)通信、  pod A与pod B的通 信、从外部⽹络访问pod以及从pod访问外部⽹络。

k8s的⽹络基于第三⽅插件实现,但是定义了⼀些插件兼容规范,该规范有CoreOS和Google联合定制,叫做 CNI(Container Network Interface)。

https://kubernetes.io/zh/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/  #CNI简 

https://github.com/containernetworking/cni/blob/spec-v0.4.0/SPEC.md #CNI版本

⽬前常⽤的的CNI⽹络插件有calico和flannel:


 

2.4.1 calico

官⽹:  https://www.projectcalico.org/

Calico是⼀个纯三层的⽹络解决⽅案,为容器提供多node间的访问通信,  calico将每⼀个node节点都当做为⼀个 由器(router),各节点通过BGP(Border Gateway Protocol) 边界⽹关协议学习并在node节点⽣成路由规则,从⽽   将不同node节点上的pod连接起来进⾏通信。

BGP是⼀个去中⼼化的协议,它通过⾃动学习和维护路由表实现⽹络的可⽤性,但是并不是所有的⽹络都⽀持      BGP ,另外为了跨⽹络实现更⼤规模的⽹络管理,  calico 还⽀持IP-in-IP的叠加模型,简称IPIP  IPIP可以实现跨不 同⽹段建⽴路由通信,但是会存在安全性问题,其在内核内置,可以通过Calico的配置⽂件设置是否启⽤IPIP, 公司内部如果k8s的node节点没有跨越⽹段建议关闭IPIP。

 

calico 核⼼组件:

 

Felix:calico的agent,运⾏在每⼀台node节点上,其主要是维护路由规则、汇报当前节点状态以确保pod的夸主 机通信。

BGP Client:每台node都运⾏,其主要负责监听node节点上由felix⽣成的路由信息,然后通过BGP协议⼴播⾄其他 剩余的node节点,从⽽相互学习路由实现pod通信。

Route Reflector:集中式的路由反射器,  calico v3.3开始⽀持,当Calico BGP客户端将路由从其                  FIB(Forward Information dataBase,转发信息库)通告到Route Reflector时,  Route Reflector会将这 些路由通告给部署集群中的其他节点,  Route Reflector专⻔⽤于管理BGP⽹络路由规则,不会产⽣pod数据通信。

注:  calico默认⼯作模式是BGP的node-to-node mesh,如果要使⽤Route Reflector需要进⾏相关配置。 https://docs.projectcalico.org/v3.4/usage/routereflector                          https://docs.projectcalico.org/v3.2/usage/routereflector/calico-routereflector

 


 

 

 

2.4.1.1 :部署过程:

https://docs.projectcalico.org/v3.4/getting-started/kubernetes/

具体过程略

 

 

2.4.1.2 :验证当前路由表:

calico 2.x 版本默认使⽤ etcd v2 API

calico 3.x 版本默认使⽤ etcd v3 API

 

root@k8s-node2:~# calicoctl  node status

Calico process is running.

 

IPv4 BGP status

+---------------+-------------------+-------+----------+-------------+

| PEER ADDRESS  |     PEER TYPE     | STATE |  SINCE   |    INFO     |

+---------------+-------------------+-------+----------+-------------+

 

|

192.168.7.101

|

node-to-node mesh

|

up

|

13:02:28

|

Established

|

|

192.168.7.102

|

node-to-node mesh

|

up

|

13:22:49

|

Established

|

|

192.168.7.110

|

node-to-node mesh

|

up

|

13:02:38

|

Established

|

+---------------+-------------------+-------+----------+-------------+

 

IPv6 BGP status

No IPv6 peers found.

 


 

2.4.1.3 :查看pod路由⾛向:

验证开启IPIP和关闭IPIP的k8s集群验证

2.4.1.3.1:开启IPIP的通信状态:

 

开启IPIP:

root@k8s-master1:~# route -n

Kernel IP routing table

 

Destination

Gateway

Genmask

Flags

Metric

Ref

Use

Iface

0.0.0.0

192.168.7.254

0.0.0.0

UG

0

0

0

eth0

172.17.0.0

0.0.0.0

255.255.0.0

U

0

0

0

docker0

172.31.13.128

192.168.7.111

255.255.255.192

UG

0

0

0

tunl0

172.31.58.64

192.168.7.110

255.255.255.192

UG

0

0

0

tunl0

172.31.89.192

0.0.0.0

255.255.255.192

U

0

0

0

*

172.31.185.128

192.168.7.102

255.255.255.192

UG

0

0

0

tunl0

192.168.0.0

0.0.0.0

255.255.248.0

U

0

0

0

eth0

 

root@k8s-master1:~# kubectl  exec -it net-test1-68898c85b7-z7rgs    sh

/ # traceroute 172.31.58.83

traceroute to 172.31.58.83 (172.31.58.83), 30 hops max, 46 byte packets

1  192.168.7.111 (192.168.7.111)  0.011 ms  0.010 ms  0.004 ms

2  172.31.58.64 (172.31.58.64)  0.300 ms  0.505 ms  0.324 ms

3  172.31.58.83 (172.31.58.83)  0.498 ms  0.619 ms  0.422 ms

/ #

2.1.1.3.2:关闭IPIP的通信状态:

需要清空环境,重新部署k8s集群

 


 

 

 

2.4.2 flannel:

官⽹:  https://coreos.com/flannel/docs/latest/

⽂档  https://coreos.com/flannel/docs/latest/kubernetes.html

由CoreOS开源的针对k8s的⽹络服务,其⽬的为解决k8s集群中各主机上的pod相互通信的问题,其借助于etcd维 护⽹络IP地址分配,并为每⼀个node服务器分配⼀个不同的IP地址段。

Flannel ⽹络模型 (后端)  Flannel⽬前有三种⽅式实现 UDP/VXLAN/host-gw:

 

UDP:早期版本的Flannel使⽤UDP封装完成报⽂的跨越主机转发,其安全性及性能略有不⾜。

VXLAN:Linux 内核在在2012年底的v3.7.0之后加⼊了VXLAN协议⽀持,因此新版本的Flannel也有UDP转换为       VXLAN,VXLAN本质上是⼀种tunnel (隧道)协议,⽤来基于3层⽹络实现虚拟的2层⽹络,⽬前flannel 的⽹络模型 已经是基于VXLAN的叠加(覆盖)⽹络,⽬前推荐使⽤vxlan作为其⽹络模型。                                                               Host-gw:也就是Host GateWay,通过在node节点上创建到达各⽬标容器地址的路由表⽽完成报⽂的转发,因此这   种⽅式要求各node节点本身必须处于同⼀个局域⽹(⼆层⽹络 )中,因此不适⽤于⽹络变动频繁或⽐较⼤型的⽹络环境, 但是其性能较好。

 

 

Flannel 组件的解释:

 

Cni0:⽹桥设备,每创建⼀个pod都会创建⼀对  veth pair,其中⼀端是pod中的eth0,另⼀端是Cni0⽹桥中的端⼝ (⽹卡),  Pod中从⽹卡eth0发出的流量都会发送到Cni0⽹桥设备的端⼝(⽹卡)上,  Cni0 设备获得的ip地址是该

节点分配到的⽹段的第⼀个地址。

Flannel.1: overlay⽹络的设备,⽤来进⾏vxlan报⽂的处理(封包和解包),不同node之间的pod数据流量都从 overlay设备以隧道的形式发送到对端。

Flannel的系统⽂件及⽬录:

 

2.4.2.1 :flannel pod状态:

需要再部署k8s的时候使⽤Flannel作为⽹络插件。


 

 

 

 

root@k8s-master1:~# kubectl

get  pods  -n kube-system

 

NAME

READY   STATUS    RESTARTS

AGE

kube-dns-75d7c6cd6f-w46pq

3/3     Running   0

13m

kube-flannel-ds-amd64-5xpbl

1/1     Running   1

22m

kube-flannel-ds-amd64-dddt2

1/1     Running   1

22m

kube-flannel-ds-amd64-jrpjn

1/1     Running   1

22m

kube-flannel-ds-amd64-qzk9f

1/1     Running   1

22m

 

2.4.2.2 :创建测试pod:

 

2.4.2.3 :验证pod状态:

 

root@k8s-master1:~# kubectl  get  pod -o wide

NAME                         READY   STATUS    RESTARTS   AGE   IP           NODE

NOMINATED NODE   READINESS GATES

 

net-test1-68898c85b7-2lgl6

192.168.7.110   <none>

1/1     Running

<none>

0

16m   172.31.3.9

net-test1-68898c85b7-7xshv

192.168.7.111   <none>

1/1     Running

<none>

0

12m   172.31.2.5

net-test1-68898c85b7-cb4s4

192.168.7.110   <none>

1/1     Running

<none>

0

16m   172.31.3.6

net-test1-68898c85b7-dctmx

192.168.7.110   <none>

1/1     Running

<none>

0

16m   172.31.3.5

 

2.4.2.4 :当前node主机IP地址范围:

 

2.4.2.5 :当前node主机cni信息:


 

 

 

root@k8s-node2:~# cat

/var/lib/cni/flannel/a77f70994d452ea66c06f0cec194d937dacac1b69c07d31b478f844f216e84c7

{"hairpinMode":true,"ipMasq":false,"ipam":{"routes":

[{"dst":"172.31.0.0/16"}],"subnet":"172.31.2.0/24","type":"host-

local"},"isDefaultGateway":true,"isGateway":true,"mtu":1

450,"name":"cbr0","type":"bridge"}

2.4.2.6 :当前node主机路由:

 

root@k8s-node2:~# route -n

Kernel IP routing table

 

Destination

Gateway

Genmask

Flags

Metric

Ref

Use Iface

0.0.0.0

192.168.7.254

0.0.0.0

UG

0

0

0 eth0

172.17.0.0

0.0.0.0

255.255.0.0

U

0

0

0 docker0

172.31.0.0

172.31.0.0

255.255.255.0

UG

0

0

0 flannel.1

172.31.1.0

172.31.1.0

255.255.255.0

UG

0

0

0 flannel.1

172.31.2.0

0.0.0.0

255.255.255.0

U

0

0

0 cni0

172.31.3.0

172.31.3.0

255.255.255.0

UG

0

0

0 flannel.1

192.168.0.0

0.0.0.0

255.255.248.0

U

0

0

0 eth0

 

2.4.2.7 :验证flannel的VXLAN配置:

验证当前backend类型:

 

kind: ConfigMap

metadata:

annotations:

kubectl.kubernetes.io/last-applied-configuration: |

{"apiVersion":"v1","data":{"cni-conf.json":"{\n

\"cniVersion\": \"0.3.1\",\n  \"plugins\": [\n    {\n

\"delegate\": {\n        \"hairpinMode\": true,\n

}\n    },\n    {\n      \"type\": \"portmap\",\n

\"portMappings\": true\n      }\n    }\n  ]\n}\n","net-conf.json":"{\n  \"Network\":

\"10.200.0.0/16\",\n  \"Backend\": {\n    \"Type\": \"vxlan\"\n

}\n}\n"},"kind":"ConfigMap","metadata":{"annotations":{},"labels":

{"app":"flannel","tier":"node"},"name":"kube-flannel-cfg","namespace":"kube-system"}}

vxlan使⽤UDP端⼝8472发送封装好的报⽂。

 

测试⽹络通信

 


 

 

 

2.4.2.8:VXLAN Directrouting:

Directrouting 为在同⼀个⼆层⽹络中的node节点启⽤直接路由机制,类似于host-gw模式。

2.4.2.8.1:修改flannel⽀持Directrouting:

需要让配置⽂件在node节点重新⽣效,

 

root@k8s-master1:/etc/ansible# vim roles/flannel/templates/kube-flannel.yaml.j2

net-conf.json: |

{

"Network": "{{ CLUSTER_CIDR }}",

"Backend": {

"Type": "{{ FLANNEL_BACKEND }}",

"Directrouting": true

}

2.4.2.8.2:验证修改后的路由表:

 


 

 

 

2.4.2.8.3:验证修改后的路由效果:

 

#改之前的路由效果

# ifconfig  eth0

eth0      Link encap:Ethernet  HWaddr BE:EE:B9:F7:62:47

inet addr:172.31.3.4  Bcast:0.0.0.0  Mask:255.255.255.0

UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1

RX packets:48 errors:0 dropped:0 overruns:0 frame:0

TX packets:35 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:0

RX bytes:3700 (3.6 KiB)  TX bytes:2286 (2.2 KiB)

 

# traceroute  172.31.2.4

traceroute to 172.31.2.4 (172.31.2.4), 30 hops max, 46 byte packets

1  172.31.3.1 (172.31.3.1)  0.049 ms  0.012 ms  0.007 ms

2  172.31.2.0 (172.31.2.0)  0.520 ms  0.639 ms  4.061 ms

3  172.31.2.4 (172.31.2.4)  3.544 ms  0.587 ms  0.464 ms

 

 

#改之后的路由效果

# ifconfig  eth0

eth0      Link encap:Ethernet  HWaddr 5E:83:2C:DD:66:D3

inet addr:172.31.3.2  Bcast:0.0.0.0  Mask:255.255.255.0

UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1

RX packets:37 errors:0 dropped:0 overruns:0 frame:0

TX packets:18 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:0

RX bytes:2824 (2.7 KiB)  TX bytes:1170 (1.1 KiB)

 

# traceroute 172.31.2.2

traceroute to 172.31.2.2 (172.31.2.2), 30 hops max, 46 byte packets

1  172.31.3.1 (172.31.3.1)  0.007 ms  0.018 ms  0.010 ms

2  192.168.7.111 (192.168.7.111)  1.174 ms  0.244 ms  2.292 ms

3  172.31.2.2 (172.31.2.2)  2.527 ms  0.549 ms  0.456 ms


 

 

 

2.4.2.9 :flannel不同node上的pod的通信:

Flannel.1 是⼀个overlay⽹络的设备,⽤来进⾏ vxlan 报⽂的处理(封包和解包),不同node之间的pod数据流量 都从overlay设备以隧道的形式发送到对端。

 

 

->: pod中产⽣数据,根据pod的路由信息,将数据发送到Cni0

->: Cni0 根据节点的路由表,将数据发送到隧道设备flannel.1

->: Flannel.1查看数据包的⽬的ip,从flanneld获得对端隧道设备的必要信息,封装数据包。 ->: Flannel.1将数据包发送到对端设备 ,对端节点的⽹卡接收到数据包

->: 对端节点发现数据包为overlay数据包,解开外层封装,并发送到到本机flannel.1设备。 ->: Flannel.1设备查看数据包,根据路由表匹配,将数据发送给Cni0设备。

->: Cni0匹配路由表,发送数据给⽹桥上对应的端⼝ (pod)

 


 

 

 

2.4.2.10 :host-gw⽹络模型:

 

# 设置flannel 后端

FLANNEL_BACKEND: "host-gw"

#FLANNEL_BACKEND: "vxlan"

#DIRECT_ROUTING: true

 

 

/ # traceroute 10.10.4.6 #跨主机容器

traceroute to 10.10.4.6 (10.10.4.6), 30 hops max, 46 byte packets

1  10.10.3.1 (10.10.3.1)  0.003 ms  0.004 ms  0.001 ms

2  172.31.6.210 (172.31.6.210)  1.166 ms  0.495 ms  0.579 ms

3  10.10.4.6 (10.10.4.6)  0.307 ms  0.335 ms  0.322 ms

/ #

/ # traceroute 172.31.6.207

traceroute to 172.31.6.207 (172.31.6.207), 30 hops max, 46 byte packets

1  10.10.3.1 (10.10.3.1)  0.003 ms  0.004 ms  0.001 ms

2  172.31.6.207 (172.31.6.207)  1.290 ms  0.776 ms  2.041 ms

 

 

2.4.2.11:  UDP⽹络模型:

UDP是最早的实现⽅式,但是由于其性能原因,现已经被废弃。


 

2.4.2.11.1:修改backend为UDP:

重新执⾏⽹络并重启master与node服务器

 

2.4.2.11.2:当前路由状态:

 

# route -n

Kernel IP routing table

 

Destination

Gateway

Genmask

Flags

Metric

Ref

Use

Iface

0.0.0.0

192.168.7.254

0.0.0.0

UG

0

0

0

eth0

172.17.0.0

0.0.0.0

255.255.0.0

U

0

0

0

docker0

172.31.0.0

0.0.0.0

255.255.0.0

U

0

0

0

flannel0

172.31.2.0

0.0.0.0

255.255.255.0

U

0

0

0

cni0

192.168.0.0

0.0.0.0

255.255.248.0

U

0

0

0

eth0

 

2.4.2.11.3:验证UDP模式下pod夸主机通信状态:

 

# kubectl  exec -it busybox sh

/ # traceroute 172.31.2.21

traceroute to 172.31.2.21 (172.31.2.21), 30 hops max, 46 byte packets

1  172.31.3.1 (172.31.3.1)  0.110 ms  0.008 ms  0.018 ms

2  *  *  *

3  *  *  *

4  172.31.2.0 (172.31.2.0)  2.801 ms  0.672 ms  0.915 ms

5  172.31.2.21 (172.31.2.21)  1.006 ms  0.736 ms  1.190 ms

2.5:术语概念:

2.5.1:  k8s中的kind类型:

 

web

当前k8s 运⾏规划图:


 

 

 

 

 

3.1:运行nginx:

将nginx运⾏在k8s中并可以从外部访问到nginx的web⻚⾯。

3.1.1:  Nginx镜像制作规划:

基于基础的centos/ubuntu/alpine镜像,制作公司内部基础镜像-Nginx基础镜像--Nginx业务镜像:

 


 

3.1.1.1 :Centos基础镜像制作:

3.1.1.1.1 :镜像⽂件列表:

 

# cd /opt/k8s-data/ #dockerfile与yaml ⽬录

# cd dockerfile/system/centos/ #系统镜像⽬录

root@k8s-master1:/opt/k8s-data/dockerfile/system/centos# tree

.

├──  build-command.sh

├──  Dockerfile

L──  filebeat-6.8.1-x86_64.rpm

0 directories, 3 files

root@k8s-master1:/opt/k8s-data/dockerfile/system/centos#

3.1.1.1.2  Dockerfile⽂件内容:

安装基础命令并配置语⾔环境为中⽂

 

root@k8s-master1:/opt/k8s-data/dockerfile/system/centos# cat Dockerfile

#制作基础镜像,centos:v7.5是基于官⽅centos 7.5镜像更改tag并上传到Harbor服务器的最原始官⽅镜像 FROM harbor.magedu.net/baseimages/centos:7.6.1810

MAINTAINER zhangshijie "zhangshijie@magedu.ent"

 

ADD  filebeat-6.8.1-x86_64.rpm /tmp/

RUN  yum install -y epel-release /tmp/filebeat-6.5.4-x86_64.rpm && rm -rf

/tmp/filebeat-6.5.4-x86_64.rpm

RUN  yum install -y vim wget tree  pcre pcre-devel gcc gcc-c++  zlib zlib-devel openssl

openssl-devel net-tools iotop unzip zip iproute ntpdate nfs-utils tcp

dump telnet traceroute

RUN rm -rf /etc/localtime && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

3.1.1.1.3 build-command脚本

基于脚本实现镜像⾃动build及上传到harbor功能

 

root@k8s-master1:/opt/k8s-data/dockerfile/system/centos# cat build-command.sh

#!/bin/bash

docker build -t harbor.magedu.net/baseimages/centos-base:v7.6 .

sleep 1

docker push harbor.magedu.net/baseimages/centos-base:v7.6

 


 

3.1.1.1.4:执⾏构建centos 基础镜像:

构建完成后⾃动上传⾄本地harbor服务器

 

3.1.1.2:  Nginx 基础镜像制作:

制作⼀个通⽤的Ningx镜像

3.1.1.3.1 :镜像⽂件列表:

 

# pwd

/opt/k8s-data/dockerfile/pub-images/nginx-base

 

# tree

.

├──  build-command.sh

├──  Dockerfile

L──  nginx-1.14.2.tar.gz

0 directories, 3 files

3.1.1.3.2  Dockerfile⽂件内容:


 

 

 

# cat Dockerfile

#Nginx Base Image

FROM harbor.magedu.net/baseimages/centos-base:v7.6

 

MAINTAINER  zhangshijie@magedu.net

 

RUN yum install -y vim wget tree  lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-

devel openssl openssl-devel iproute net-tools iotop

ADD nginx-1.14.2.tar.gz /usr/local/src/

RUN cd /usr/local/src/nginx-1.14.2 && ./configure  && make && make install && ln -sv

/usr/local/nginx/sbin/nginx /usr/sbin/nginx && useradd nginx -u 2001

3.1.1.1.3 build-command脚本

 

# cat build-command.sh

#!/bin/bash

docker build -t harbor.magedu.net/pub-images/nginx-base:v1.14.2  .

sleep 1

docker push  harbor.magedu.net/pub-images/nginx-base:v1.14.2

3.1.1.1.4:执⾏构建Nginx基础镜像:

 

3.1.1.3:  Nginx业务镜像制作:

基于Nginx基础镜像,制作N个不同服务的Nginx业务镜像:

3.1.1.3.1 :镜像⽂件列表:


 

 

 

# pwd

/opt/k8s-data/dockerfile/linux36/nginx

# tree

.

├──  build-command.sh

├──  Dockerfile

├──  index.html

├──  nginx.conf

webapp

L  index.html

1 directory, 5 files

3.1.1.3.2  Dockerfile文件内容:

 

# cat  Dockerfile

#Nginx Base Image

FROM harbor.magedu.net/pub-images/nginx-base:v1.14.2

 

ADD nginx.conf /usr/local/nginx/conf/nginx.conf

ADD webapp/*  /usr/local/nginx/html/webapp/

ADD index.html  /usr/local/nginx/html/index.html

#RUN mkdir /usr/local/nginx/html/webapp/about /usr/local/nginx/html/webapp/images

 

EXPOSE 80 443

 

CMD ["nginx"]

3.1.1.3.3 build-command脚本

 

3.1.1.3.4:测试⻚⾯⽂件内容:

 

3.1.1.3.5  Nginx配置文件:

 


 

 

 

3.1.1.3.6:执行构建Nginx 业务镜像:

 


 

3.1.1.3.7:测试nginx业务镜像可以启动为容器:

 

3.1.1.3.8:访问测试Nginx业务web⻚⾯:

 

3.1.2:yaml⽂件及语法基础:

需要提前创建好yaml⽂件,并创建好好pod运⾏所需要的namespace 、yaml⽂件等资源

3.1.2.1 :创建业务namespace yaml⽂件:

 

# pwd

/opt/k8s-data/yaml/

# mkdir namespaces

# cd namespaces

 

# cat linux36.yaml

apiVersion: v1 #API版本

kind: Namespace #类型为namespac

metadata:  #定义元数据

name: linux36 #namespace名称

3.1.2.2 :创建并验证namespace:

 

# kubectl  apply -f linux36.yaml

namespace/linux36 created

 

# kubectl  get namespaces

NAME          STATUS   AGE

default       Active   21d

kube-public   Active   21d

kube-system  Active   21d

linux36       Active   45s

3.1.2.2:yaml与json:

yaml和json对⽐,在线yaml与json编辑器:  http://www.bejson.com/validators/yaml_editor/


 

3.1.2.2.1:json格式:

 

{ "⼈员名单 '":

{ "张三": { "年龄": 18, "职业": "Linux运维⼯程师", "爱好": [ "看书", "学习", "加班" ] }, #

"李四": { "年龄": 20, "职业": "Java开发⼯程师", "爱好": [ "开源技术", "微服务", "分布式存 储 "] } } }

#json特点:

json 不能注释

json 可读性较差

json 语法很严

⽐较适⽤于API 返回值,也可⽤于配置⽂件

3.1.2.2.2 :yaml格式:

 

员名单 :

:

 : 18 #

职业 : Linux运维⼯程师

爱好 :

- 看书

- 学习

- 加班

 

:

年龄 : 20

职业 : Java开发⼯程师  # 这是职业

爱好 :

- 开源技术

- 微服务

- 分布式存储

 

⼤⼩写敏感

使⽤缩进表示层级关系

缩进时不允许使⽤Tal键,只允许使⽤空格

缩进的空格数⽬不重要,只要相同层级的元素左侧对⻬即可

使⽤ ”#” 表示注释,从这个字符⼀直到⾏尾,都会被解析器忽略

json适⽤于配置⽂件

3.1.2.2.3 :yaml文件主要特性:

k8s中的yaml⽂件以及其他场景的yaml⽂件,⼤部分都是以下类型:

 


 

3.1.2.2.4  Nginx 业务yaml文件详解:

 

# pwd

/opt/k8s-data/yaml/linux36

# mkdir nginx tomcat-app1  tomcat-app2

# cd nginx/

 

# pwd

/opt/k8s-data/yaml/linux36/nginx

# cat nginx.yaml

kind: Deployment  #类型,是deployment控制器,  kubectl explain  Deployment           apiVersion: extensions/v1beta1  #API版本,  # kubectl explain  Deployment.apiVersion metadata: #pod的元数据信息,  kubectl explain  Deployment.metadata

labels: # ⾃定义pod的标签,  # kubectl explain  Deployment.metadata.labels

app: linux36-nginx-deployment-label #标签名称为app值为linux36-nginx-deployment-label

后⾯会⽤到此标签

name: linux36-nginx-deployment #pod的名称

namespace: linux36 #pod的namespace,默认是defaule

spec: #定义deployment中容器的详细信息,  kubectl explain  Deployment.spec

replicas: 1 #创建出的pod的副本数,即多少个pod,默认值为1

selector: #定义标签选择器

matchLabels: #定义匹配的标签,必须要设置

app: linux36-nginx-selector #匹配的⽬标标签,

template: #定义模板,必须定义,模板是起到描述要创建的pod的作⽤

metadata: #定义模板元数据

labels: #定义模板label,Deployment.spec.template.metadata.labels

app: linux36-nginx-selector #定义标签,等于Deployment.spec.selector.matchLabels spec: #定义pod信息

containers:#定义pod中容器列表,可以多个⾄少⼀个,  pod不能动态增减容器

- name: linux36-nginx-container #容器名称

image: harbor.magedu.net/linux36/nginx-web1:v1 #镜像地址

#command: ["/apps/tomcat/bin/run_tomcat.sh"] #容器启动执⾏的命令或脚本

#imagePullPolicy: IfNotPresent

imagePullPolicy: Always #拉取镜像策略

ports: #定义容器端⼝列表

- containerPort: 80 #定义⼀个端⼝ protocol: TCP #端⼝协议

name: http #端⼝名称

- containerPort: 443 #定义⼀个端⼝ protocol: TCP #端⼝协议

name: https #端⼝名称

env: #配置环境变量

- name: "password" #变量名称。必须要⽤引号引起来 value: "123456" #当前变量的值

- name: "age" #另⼀个变量名称

value: "18" #另⼀个变量的值

resources: #对资源的请求设置和限制设置

limits: #资源限制设置,上限

cpu: 500m #cpu的限制,单位为core数,可以写0.5或者500mCPU压缩值


 

memory: 2Gi #内存限制,单位可以为Mib/Gib,将⽤于docker run --memory参数 requests: #资源请求的设置

cpu: 200m #cpu请求数,容器启动的初始可⽤数量 ,可以写0.5或者500m等CPU压缩值

memory: 512Mi #内存请求⼤⼩,容器启动的初始可⽤数量,⽤于调度pod时候使⽤

 

 

---

kind: Service #类型为service

apiVersion: v1 #service API版本,    service.apiVersion

metadata: #定义service元数据,  service.metadata

labels: #⾃定义标签,  service.metadata.labels

app: linux36-nginx #定义service标签的内容

name: linux36-nginx-spec #定义service的名称,此名称会被DNS解析

namespace: linux36 #该service⾪属于的namespaces名称,即把service创建到哪个namespace⾥⾯ spec: #定义service的详细信息,  service.spec

type: NodePort #service的类型,定义服务的访问⽅式,默认为ClusterIP    service.spec.type ports: #定义访问端⼝,    service.spec.ports

- name: http #定义⼀个端⼝名称   port: 80 #service 80端⼝        protocol: TCP #协议类型           targetPort: 80 # ⽬标pod的端⼝

nodePort: 30001 #node节点暴露的端⼝

- name: https #SSL 端⼝

port: 443 #service 443端⼝

protocol: TCP #端⼝协议

targetPort: 443 # ⽬标pod端⼝

nodePort: 30043 #node节点暴露的SSL端⼝

selector: #service的标签选择器,定义要访问的⽬标pod

app: linux36-nginx #将流量路到选择的pod上,须等于Deployment.spec.selector.matchLabels

3.1.3:  k8s中创建Nginx pod:

创建Nginx pod 并测试通过node port访问

3.1.3.1:  Nginx yaml文件:

 


 

template:

metadata:

labels:

app: linux36-nginx-selector

spec:

containers:

- name: linux36-nginx-container

image: harbor.magedu.net/linux36/nginx-web1:v1

#command: ["/apps/tomcat/bin/run_tomcat.sh"]

#imagePullPolicy: IfNotPresent

imagePullPolicy: Always

ports:

- containerPort: 80 protocol: TCP    name: http

- containerPort: 443

protocol: TCP

name: https

env:

- name: "password"

value: "123456"

- name: "age"

value: "18"

resources:

limits:

cpu: 2

memory: 2Gi

requests:

cpu: 500m

memory: 1Gi

 

 

 

---

kind: Service

apiVersion: v1

metadata:

labels:

app: linux36-nginx-service-label

name: linux36-nginx-service

namespace: linux36

spec:

type: NodePort

ports:

- name: http

port: 80

protocol: TCP

targetPort: 80

nodePort: 30002

- name: https


 

 

 

3.1.3.2 :创建Nginx pod:

 

3.1.3.3 :测试访问Nginx web界⾯:

 

 

 

3.2:运⾏tomcat

基于基础的centos镜像,制作公司内部基础镜像--jdk镜像--tomcat基础镜像--tomcat业务镜像:

3.2.1:JDK基础镜像制作:

3.2.1.1:JDK基础镜像⽂件列表:

 

# pwd

/opt/k8s-data/dockerfile/pub-images #共⽤镜像⽬录

# cd jdk-1.8.212/

# tree

.

├──  build-command.sh

├──  Dockerfile

├──  jdk-8u212-linux-x64.tar.gz

L  profile

0 directories, 4 files

3.2.1.2:  Dockerfile⽂件内容:

 


 

 

 

3.2.1.3 :build-command脚本:

 

3.2.1.4 :执⾏构建JDK基础镜像:

 

3.2.1.5 :验证JDK镜像启动为容器后的java环境:

 


 

3.2.2 :tomcat基础镜像制作:

3.2.2.1 :基础镜像⽂件列表:

 

# pwd

/opt/k8s-data/dockerfile/pub-images/tomcat-base

# tree

.

├──  apache-tomcat-8.5.43.tar.gz

├──  build-command.sh

L  Dockerfile

0 directories, 3 files

3.2.2.2:  Dockerfile⽂件内容:

 

# cat Dockerfile

#JDK Base Image

FROM harbor.magedu.net/pub-images/jdk-base:v8.212

 

MAINTAINER zhangshijie "zhangshijie@magedu.net"

 

RUN mkdir /apps /data/tomcat/webapps /data/tomcat/logs -pv

ADD apache-tomcat-8.5.43.tar.gz  /apps

RUN ln -sv /apps/apache-tomcat-8.5.43 /apps/tomcat && chown -R tomcat.tomcat /apps

/data -R

#ADD  filebeat-6.4.2-x86_64.rpm /tmp/

#RUN  yum install -y /tmp/filebeat-6.4.2-x86_64.rpm && rm -rf /tmp/filebeat-6.4.2-

x86_64.rpm

3.2.3.3 :build-command脚本:

 

# cat build-command.sh

#!/bin/bash

docker build -t harbor.magedu.net/pub-images/tomcat-base:v8.5.43  .

sleep 3

docker push  harbor.magedu.net/pub-images/tomcat-base:v8.5.43

3.2.3.4 :构建tomcat基础镜像:


 

 

 

3.2.3.5 :测试访问tomcat基础镜像启动为容器:

 

# docker run -it --rm -p 8801:8080 harbor.magedu.net/pub-images/tomcat-base:v8.5.43

/apps/tomcat/bin/catalina.sh  start

/apps/tomcat

/apps/tomcat

/apps/tomcat/temp

/usr/local/jdk/jre

/apps/tomcat/bin/bootstrap.jar:/apps/tomcat/bin/tomcat-juli.jar

 

 

 


 

 

 

3.2.3 :tomcat业务镜像app1制作:

后期按此步骤制作app2 、appN镜像

3.2.3.1 :cat业务镜像⽂件列表:

 

# pwd

/opt/k8s-data/dockerfile/linux36/tomcat-app1

 

# tree

.

├──  app1.tar.gz

├──  build-command.sh

├──  catalina.sh

├──  Dockerfile

├──  filebeat.yml

├──  myapp

L──  index.html

├──  run_tomcat.sh

L  server.xml

1 directory, 8 files

3.2.3.2:  Dockerfile⽂件内容:

 

# cat Dockerfile

#tomcat web1

FROM harbor.magedu.net/pub-images/tomcat-base:v8.5.43

 

ADD catalina.sh /apps/tomcat/bin/catalina.sh

ADD server.xml /apps/tomcat/conf/server.xml

#ADD myapp/* /data/tomcat/webapps/myapp/

ADD app1.tar.gz /data/tomcat/webapps/myapp/

ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh

#ADD filebeat.yml /etc/filebeat/filebeat.yml

RUN chown  -R tomcat.tomcat /data/ /apps/

 

EXPOSE 8080 8443

 

CMD ["/apps/tomcat/bin/run_tomcat.sh"]

 


 

3.2.3.3 :build-command脚本:

 

# cat  build-command.sh

#!/bin/bash

TAG=$1

docker build -t  harbor.magedu.net/linux36/tomcat-app1:${TAG} .

sleep 3

docker push  harbor.magedu.net/linux36/tomcat-app1:${TAG}

3.2.3.4 :执⾏构建tomcat业务镜像:

 

 

 

 

3.2.3.5 :测试tomcat业务镜像启动为容器:

 


 

 

 

3.2.3.6 :访问tomcat业务镜像web⻚⾯:

 

3.2.4:在k8s环境运⾏tomcat:

3.2.4.1 :创建tomcat业务pod:

 

# pwd

/opt/k8s-data/yaml/linux36/tomcat-app1

 

# kubectl  apply  -f  tomcat-app1.yaml

deployment.extensions/linux36-tomcat-app1-deployment created

service/linux36-tomcat-app1-service created

3.2.4.2 :验证pod启动成功:

 

3.2.4.3 :测试访问tomcat业务pod的nodeport:

 

3.3:  k8s中nginx+tomcat实现动静分离:

实现⼀个通⽤的nginx+tomcat动静分离web架构,即⽤户访问的静态⻚⾯和图⽚在由nginx直接响应,⽽动态请求 则基于location转发⾄tomcat。

重点:  Nginx基于tomcat的service name转发⽤户请求到tomcat业务app

3.3.1:查看tomcat app1的server name:

 


 

3.3.2:  nginx业务镜像配置:

3.3.2.1 :nginx配置⽂件:

 

upstream  tomcat_webserver {

server  linux36-tomcat-app1-service.linux36.svc.linux36.local:80;

}

 

server {

location /myapp {

proxy_pass  http://tomcat_webserver;

proxy_set_header   Host    $host;

proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header X-Real-IP $remote_addr;

}

}

3.3.2.3 :重新构建nginx业务镜像:

 

3.3.2.3 :镜像启动为容容器并验证配置⽂件:


 

 

 

3.3.3:重新创建业务nginx pod:

两种实现⽅式

3.3.3.1 :删除并重新创建nginx业务镜像:

 

# pwd

/opt/k8s-data/yaml/linux36/nginx

 

# kubectl  delete -f nginx.yaml

# vim nginx.yaml

image: harbor.magedu.net/linux36/nginx-web1:v1 #更新镜像地址

# kubectl  apply -f nginx.yaml

3.3.3.2 :更新nginx业务镜像版本号:

重新构建新版本镜像,然后打⼀个新的tag号,然后通过指定镜像的⽅式对pod进⾏更新。


 

3.3.3.2.1:准备新版本nginx业务镜像:

 

3.3.3.2.2:获取当前deployment:

 

 

# kubectl  get deployment -n linux36

 

 

 

NAME                             READY

UP-TO-DATE

AVAILABLE

AGE

linux36-nginx-deployment         1/1

1

1

7m30s

linux36-tomcat-app1-deployment   1/1

1

1

45m

 

3.3.3.2.3:执⾏更新nginx业务镜像版本:

 

# kubectl set image deployment/linux36-nginx-deployment  linux36-nginx-

container=harbor.magedu.net/linux36/n

ginx-web1:v2 -n linux36deployment.extensions/linux36-nginx-deployment image updated

3.3.3.3 :web访问测试:

验证能否通过nginx访问到tomcat的app项⽬

 

3.4:基于NFS实现动静分离:

图⽚的上传由后端服务器tomcat完成,图⽚的读取由前端的nginx响应,就需要nginx与tomcat的数据保持⼀致 性,因此需要将数据保存到k8s环境外部的存储服务器,然后再挂载到各nginx与tomcat 的容器中进⾏相应的操 作。

http://docs.kubernetes.org.cn/429.html  #存储卷类型及使⽤

3.4.1:  NFS 服务器环境准备:

 

# mkdir  /data/linux36 -p  #数据总⽬录

# mkdir /data/linux36/images  #图⽚⽬录

# mkdir /data/linux36/static  #静态⽂件⽬录

# vim  /etc/exports

/data/linux36 *(rw,no_root_squash)

# systemctl  restart nfs-server

 


 

3.4.2:  NFS客户端挂载并测试写⼊⽂件:

 

3.4.3:  nginx 业务容器yaml:

 

# cat nginx.yaml

kind: Deployment

apiVersion: extensions/v1beta1

metadata:

labels:

app: linux36-nginx-deployment-label

name: linux36-nginx-deployment

namespace: linux36

spec:

replicas: 1

selector:

matchLabels:

app: linux36-nginx-selector

template:

metadata:

labels:

app: linux36-nginx-selector

spec:

containers:

- name: linux36-nginx-container

image: harbor.magedu.net/linux36/nginx-web1:v1

#command: ["/apps/tomcat/bin/run_tomcat.sh"]

#imagePullPolicy: IfNotPresent

imagePullPolicy: Always

ports:

- containerPort: 80 protocol: TCP    name: http

- containerPort: 443

protocol: TCP

name: https

env:

- name: "password"

value: "123456"

- name: "age"

value: "18"

resources:

limits:

cpu: 2

memory: 2Gi

requests:


 

 

cpu: 500m

memory: 1Gi

volumeMounts:

- name: linux36-images

mountPath: /usr/local/nginx/html/webapp/images

readOnly: false

- name: linux36-static

mountPath: /usr/local/nginx/html/webapp/static

readOnly: false

volumes: #kubectl  explain Deployment.spec.template.spec.volumes

- name: linux36-images

nfs:

server: 192.168.7.108

path: /data/linux36/images

- name: linux36-static

nfs:

server: 192.168.7.108

path: /data/linux36/static

 

---

kind: Service

apiVersion: v1

metadata:

labels:

app: linux36-nginx-service-label

name: linux36-nginx-service

namespace: linux36

spec:

type: NodePort

ports:

- name: http

port: 80

protocol: TCP

targetPort: 80

nodePort: 30002

- name: https  port: 443    protocol: TCP

targetPort: 443

nodePort: 30443

selector:

app: linux36-nginx-selector


 

3.4.4:执⾏更新yaml⽂件:

 

3.4.5:  pod中验证NFS挂载:

 

3.4.6 :tomcat业务pod更新挂载:

 


 

- name: linux36-tomcat-app1-container

image: harbor.magedu.net/linux36/tomcat-app1:2019-08-02_11_02_30

#command: ["/apps/tomcat/bin/run_tomcat.sh"]

#imagePullPolicy: IfNotPresent

imagePullPolicy: Always

ports:

- containerPort: 8080

protocol: TCP

name: http

#env:

#- name: "password"

#  value: "123456"

#- name: "age"

#  value: "18"

#resources:

#  limits:

#    cpu: 4

#    memory: 4Gi

#  requests:

#    cpu: 2

#    memory: 4Gi

 

volumeMounts:

- name: linux36-images

mountPath:  /data/tomcat/webapps/myapp/images

readOnly: false

- name: linux36-static

mountPath:  /data/tomcat/webapps/myapp/static

readOnly: false

volumes:

- name: linux36-images

nfs:

server: 192.168.7.108

path: /data/linux36/images

- name: linux36-static

nfs:

server: 192.168.7.108

path: /data/linux36/static

 

---

kind: Service

apiVersion: v1

metadata:

labels:

app: linux36-tomcat-app1-service-label

name: linux36-tomcat-app1-service

namespace: linux36

spec:

type: NodePort


 

 

 

3.4.7:执⾏更新tomcat app1业务容器yaml:

 

root@k8s-master1:/opt/k8s-data/yaml/linux36/tomcat-app1# kubectl  apply -f tomcat-

app1.yaml

deployment.extensions/linux36-tomcat-app1-deployment configured

service/linux36-tomcat-app1-service unchanged

3.4.8:验证tomcat app1业务容器NFS挂载:

 

3.4.9:访问web测试:

⼿动祥NFS⽬录分别上传图⽚和html⽂件,测试访问

3.4.9.1 :上传数据到NFS:

 


 

3.4.9.2 :访问nginx 业务pod:

http://192.168.7.110:30002/myapp/images/1.jpg

 

3.4.9.3 :访问tomcat业务pod:

 

 


 

3.4.5:命令总结:

http://docs.kubernetes.org.cn/

 

 

 

# kubectl

get service    --all-namespaces -o wide

# kubectl

get  pods      --all-namespaces -o wide

# kubectl

get  nodes     --all-namespaces -o wide

# kubectl

get deployment --all-namespaces

# kubectl

get deployment -n linux35 -o wide #更改显示格式

# kubectl

describe pods linux35-tomcat-app1-deployment -n linux35 #查看某个资源详细信息

# kubectl

create -f tomcat-app1.yaml

# kubectl

apply  -f tomcat-app1.yaml

# kubectl

delete -f tomcat-app1.yaml

# kubectl

create -f tomcat-app1.yaml  --save-config --record

# kubectl

apply -f tomcat-app1.yaml  --record #推荐命令

# kubectl

exec -it linux35-tomcat-app1-deployment-6bccd8f9c7-g76s5 bash  -n linux35

# kubectl

logs  linux35-tomcat-app1-deployment-6bccd8f9c7-g76s5   -n linux35

# kubectl

delete pods  linux35-tomcat-app1-deployment-6bccd8f9c7-g76s5   -n linux35

 

 

 

四:  k8s 运维示例:

和运维相关的⽇常运维事宜

4.1:⼿动调整pod数量:                                                             

kubectl  scale 对运⾏在k8s 环境中的pod 数量进⾏扩容(增加)或缩容(减⼩)。

 


 

 

 

4.2  HPA自动伸缩pod数量:                                                     

kubectl  autoscale ⾃动控制在k8s集群中运⾏的pod数量(⽔平⾃动伸缩),需要提前设置pod范围及触发条件。

k8s从1.1版本开始增加了名称为HPA(Horizontal Pod Autoscaler)的控制器,⽤于实现基于pod中资源

(CPU/Memory)利⽤率进⾏对pod的⾃动扩缩容功能的实现,早期的版本只能基于Heapster组件实现对CPU利⽤率 做为触发条件,但是在k8s 1.11版本开始使⽤Metrices Server完成数据采集,然后将采集到的数据通过                  API(Aggregated API,汇总API),例如metrics.k8s.io 、custom.metrics.k8s.io 、external.metrics.k8s.io,然后 再把数据提供给HPA控制器进⾏查询,以实现基于某个资源利⽤率对pod进⾏扩缩容的⽬的。

 

控制管理器默认每隔15s (可以通过horizontal-pod-autoscaler-sync-period修改)查询metrics的资源使

⽤情况

⽀持以下三种metrics指标类型:

->预定义metrics (⽐如Pod的CPU)以利⽤率的⽅式计算

-> ⾃定义的Pod metrics,以原始值(raw value)的⽅式计算

-> ⾃定义的 object metrics

⽀持两种metrics查询⽅式:

->Heapster

-> ⾃定义的REST API

⽀持多metrics

 


 

4.2.1:准备metrics-server:

使⽤metrics-server作为HPA数据源。

https://github.com/kubernetes-sigs/metrics-server

4.2.1.1 :clone代码:

 

4.2.1.2 :准备image:

 

测试系统⾃带的指标数据:

# curl http://localhost:8080/apis/metrics.k8s.io/v1beta1/nodes

# curl http://localhost:8080/apis/metrics.k8s.io/v1beta1/pods

 

测试指标数据:

# kubectl  top

# kubectl  top nodes #报错如下

Error from server (NotFound): the server could not find the requested resource (get

services http:heapster:)

 

解决⽅案:

# docker pull  k8s.gcr.io/metrics-server-amd64:v0.3.5 #google镜像仓库

# docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server- amd64:v0.3.5 #阿⾥云镜像仓库

或者

# docker tag k8s.gcr.io/metrics-server-amd64:v0.3.5

harbor.magedu.net/baseimages/metrics-server-amd64:v0.3.5

# docker push harbor.magedu.net/baseimages/metrics-server-amd64:v0.3.5

The push refers to repository [harbor.magedu.net/baseimages/metrics-server-amd64]

5f70bf18a086: Mounted from baseimages/heapster-influxdb-amd64

a41f1d5bc0e0: Pushed

3c0f8dc299d8: Pushed

v0.3.3: digest: sha256:e8efd0115ca97461715981072148cc1c8f33a06c9e0d3a34b18396cd1e7623a4

size: 944

4.1.2.3 :修改yaml文件:

 


 

metadata:

name: metrics-server

namespace: kube-system

---

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: metrics-server

namespace: kube-system

labels:

k8s-app: metrics-server

spec:

selector:

matchLabels:

k8s-app: metrics-server

template:

metadata:

name: metrics-server

labels:

k8s-app: metrics-server

spec:

serviceAccountName: metrics-server

volumes:

# mount in tmp so we can safely use from-scratch images and/or read-only

containers

- name: tmp-dir

emptyDir: {}

containers:

- name: metrics-server

image: harbor.magedu.net/baseimages/metrics-server-amd64:v0.3.5 #本地harbor

imagePullPolicy: Always

volumeMounts:

- name: tmp-dir  mountPath: /tmp

4.1.2.4 :创建metrics-server服务:

 

# kubectl  apply  -f deploy/1.8+/

clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created

clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator

created

rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created

apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created

serviceaccount/metrics-server created

deployment.extensions/metrics-server created

service/metrics-server created

clusterrole.rbac.authorization.k8s.io/system:metrics-server created

clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created

 


 

4.1.2.5 :验证metrics-server pod:

 

验证metrics-server 是否采集到node数据:

 

验证metrics-server 是否采集到pod数据:

 

root@k8s-master1:/opt# kubectl  top nodes

NAME           CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%

172.31.7.101   285m         7%     1802Mi          55%

172.31.7.102   249m         6%     1853Mi          57%

172.31.7.103   226m         5%     1780Mi          55%

172.31.7.111   138m         3%     1463Mi          28%

172.31.7.112   132m         3%     1478Mi          28%

172.31.7.113   117m         2%     1469Mi          28%

 

root@k8s-master1:/opt# kubectl  top pods  -n default

NAME        CPU(cores)   MEMORY(bytes)

busybox     0m           0Mi

net-test1   0m           1Mi

net-test2   0m           1Mi

net-test3   0m           0Mi

net-test4   0m           0Mi

4.1.2.6 :修改controller-manager启动参数:

 


 

 

 

--horizontal-pod-autoscaler-cpu-initialization-period  duration  The period after

pod start when CPU samples might be skipped. (default 5m0s)

#⽤于设置  pod 的初始化时间,    在此时间内的  podCPU 资源指标将不会被采纳,默认为5分钟

--horizontal-pod-autoscaler-initial-readiness-delay duration The period after pod

start during which readiness changes will be treated as initial readiness. (default

30s)

#⽤于设置  pod 准备时间    在此时间内的  pod 统统被认为未就绪及不采集数据 ,默认为30

 

 

# vim /etc/systemd/system/kube-controller-manager.service

[Unit]

Description=Kubernetes Controller Manager

Documentation=https://github.com/GoogleCloudPlatform/kubernetes

 

[Service]

ExecStart=/usr/bin/kube-controller-manager \

--address=127.0.0.1 \

--master=http://127.0.0.1:8080 \

--allocate-node-cidrs=true \

--service-cluster-ip-range=10.20.0.0/16 \

--cluster-cidr=172.31.0.0/16 \

--cluster-name=kubernetes \

--cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \

--cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \

--service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \

--root-ca-file=/etc/kubernetes/ssl/ca.pem \

--horizontal-pod-autoscaler-use-rest-clients=true \

--leader-elect=true \

--horizontal-pod-autoscaler-use-rest-clients=true \ #是否使⽤其他客户端数据 --horizontal-pod-autoscaler-sync-period=10s \

--v=2

Restart=on-failure

RestartSec=5

 

[Install]

WantedBy=multi-user.target

 

4.1.2.6 :重启controller-manager:

验证以上参数是否⽣效

 


 

4.2.1 :通过命令配置扩缩容:

 

# kubectl  autoscale deployment/nginx-deployment --min=2 --max=10 --cpu-percent=80 -n

magedu

horizontalpodautoscaler.autoscaling/nginx-deployment autoscaled

 

# kubectl  autoscale deployment/linux36-nginx-deployment    --min=2 --max=10 --cpu-

percent=80 -n linux36

horizontalpodautoscaler.autoscaling/linux36-nginx-deployment autoscaled

 

 

验证信息:

# kubectl describe  deployment/linux36-nginx-deployment    -n linux36

desired 最终期望处于READY状态的副本数

updated 当前完成更新的副本数

total 总计副本数

available 当前可⽤的副本数

unavailable 不可⽤副本数

 

4.2.2:yaml⽂件中定义扩缩容配置:

定义在tomcat服务中的yaml中

 


 

selector:

matchLabels:

app: linux36-tomcat-app1-selector

template:

metadata:

labels:

app: linux36-tomcat-app1-selector

spec:

containers:

- name: linux36-tomcat-app1-container

image: harbor.magedu.net/linux36/tomcat-app1:2019-08-02_11_02_30

#command: ["/apps/tomcat/bin/run_tomcat.sh"]

#imagePullPolicy: IfNotPresent

imagePullPolicy: Always

ports:

- containerPort: 8080

protocol: TCP

name: http

#env:

#- name: "password"

#  value: "123456"

#- name: "age"

#  value: "18"

#resources:

#  limits:

#    cpu: 4

#    memory: 4Gi

#  requests:

#    cpu: 2

#    memory: 4Gi

 

volumeMounts:

- name: linux36-images

mountPath:  /data/tomcat/webapps/myapp/images

readOnly: false

- name: linux36-static

mountPath:  /data/tomcat/webapps/myapp/static

readOnly: false

volumes:

- name: linux36-images

nfs:

server: 192.168.7.108

path: /data/linux36/images

- name: linux36-static

nfs:

server: 192.168.7.108

path: /data/linux36/static

 

---


 

kind: Service

apiVersion: v1

metadata:

labels:

app: linux36-tomcat-app1-service-label

name: linux36-tomcat-app1-service

namespace: linux36

spec:

type: NodePort

ports:

- name: http

port: 80

protocol: TCP

targetPort: 8080

nodePort: 30003

selector:

app: linux36-tomcat-app1-selector

 

---

apiVersion: autoscaling/v2beta1 #定义API版本

kind: HorizontalPodAutoscaler  #对象类型

metadata: #定义对象元数据

namespace: linux36 #创建后⾪属的namespace

name: linux36-tomcat-app1-podautoscaler #对象名称

labels: 这样的label标签

app: linux36-tomcat-app1 # ⾃定义的 label名称

version: v2beta1 # ⾃定义的 api版本

spec: #定义对象具体信息

scaleTargetRef: #定义⽔平伸缩的⽬标对象,  DeploymentReplicationController/ReplicaSet

apiVersion: apps/v1

#API版本,  HorizontalPodAutoscaler.spec.scaleTargetRef.apiVersion

kind: Deployment #⽬标对象类型为deployment

name: linux36-tomcat-app1-deployment  #deployment 的具体名称

minReplicas: 2 #最⼩pod数

maxReplicas: 5 #最⼤ pod数

metrics: #调⽤ metrics数据定义

- type: Resource #类型为资源 resource:  #定义资源

name: cpu #资源名称为cpu

targetAverageUtilization: 80 #CPU使⽤率

- type: Resource  #类型为资源 resource:  #定义资源

name: memory #资源名称为memory

targetAverageValue: 1024Mi   #memory使⽤率


 

4.2.3:验证HPA:

 

验证扩容、缩容效果:

 

4.2.4:配置⾃动扩缩容:

先⼿动扩容⾄5个,验证在空闲时间是否会⾃动缩容

4.2.4.1 :将pod扩容⾄5个:

 

4.2.4.2 :验证HPA⽇志:

空闲⼀段时间,验证是否会对容器扩缩容


 

 

 

root@k8s-master1:~# kubectl  get hpa -n linux36

NAME                                REFERENCE                                   TARGETS

M

INPODS   MAXPODS   REPLICAS   AGElinux36-tomcat-app1-podautoscaler

Deployment/linux36-tomcat-app1-deployment   <unknown>/200Mi, 0%/80%   2

5         4          10m

root@k8s-master1:~# kubectl   describe hpa linux36-tomcat-app1-podautoscaler  -n

linux36

Events:

Type    Reason             Age    From                       Message

----    ------             ----   ----                       -------

Normal  SuccessfulRescale  5m52s  horizontal-pod-autoscaler  New size: 5; reason:

Current number of replicas above Spec.MaxReplicas

Normal  SuccessfulRescale  8s     horizontal-pod-autoscaler  New size: 1; reason: All

metrics below target

kubernetes v1.15

 

kubernetes v1.19

 


⽤于临时修改某些配置后需要⽴即⽣效的场景

 

# kubectl  get deployment -n linux36

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE

linux36-nginx-deployment         4/4     4            4           5h48m

linux36-tomcat-app1-deployment   5/5     5            5           19m

# kubectl  edit deployment linux36-nginx-deployment -n linux36 #修改副本数/镜像地址

# kubectl  get  pods  -n linux36 #验证副本数是否与edit编辑之后的⼀

NAME                                              READY   STATUS    RESTARTS   AGE

linux36-nginx-deployment-9968c6f5c-8twhk          1/1     Running   0          5h14m

linux36-nginx-deployment-9968c6f5c-r97xm          1/1     Running   0          38m

linux36-nginx-deployment-9968c6f5c-txlmm          1/1     Running   0          109m

4.4:定义node资源标签:

lable是⼀个键值对,创建pod的时候会查询那些node有这个标签,只会将pod创建在符合指定label值的node节点 上。

4.4.1:查看当前node label:

 

 

# kubectl describe

node 192.168.7.110

Name:

192.168.7.110

Roles:

node

Labels:

beta.kubernetes.io/arch=amd64

beta.kubernetes.io/os=linux

kubernetes.io/hostname=192.168.7.110

kubernetes.io/role=node

.......略!

 

 

4.4.2:⾃定义node label并验证:

 

# kubectl  label node  192.168.7.110 project=linux36

node/192.168.7.110 labeled

 

# kubectl label nodes 192.168.7.110  test_label=test

node/192.168.7.110 labeled

 


 

 

 

4.4.3:yaml引用node label:

 

root@k8s-master1:/opt/k8s-data/yaml/linux36/nginx# cat nginx.yaml

kind: Deployment

apiVersion: extensions/v1beta1

metadata:

labels:

app: linux36-nginx-deployment-label

name: linux36-nginx-deployment

namespace: linux36

spec:

replicas: 1

selector:

matchLabels:

app: linux36-nginx-selector

template:

metadata:

labels:

app: linux36-nginx-selector

spec:

containers:

- name: linux36-nginx-container

image: harbor.magedu.net/linux36/nginx-web1:v1

#command: ["/apps/tomcat/bin/run_tomcat.sh"]

#imagePullPolicy: IfNotPresent

imagePullPolicy: Always

ports:

- containerPort: 80 protocol: TCP    name: http

- containerPort: 443

protocol: TCP

name: https

env:

- name: "password"

value: "123456"

- name: "age"

value: "18"

resources:


 

 

 

4.4.4:应⽤yaml⽂件:

 

# pwd

/opt/k8s-data/yaml/linux36/nginx

 

apply  -f  nginx.yaml

get pods  -o wide -n linux36 #pod运⾏到了指定的node节点上

READY   STATUS             RESTARTS   AGE

NODE            NOMINATED NODE   READIN

ESS GATESlinux36-nginx-deployment-768c7fcb8-5dcq2   0/1     CrashLoopBackOff   5

3m32s   172.31.58.121   192.168.7.110   <none>           <none

4.4.5:删除⾃定义node label:

 


 

 

 

4.5:业务镜像版本升级及回滚:

在指定的deployment中通过kubectl set  image指定新版本的 镜像:tag 来实现更新代码的⽬的。

构建三个不同版本的nginx镜像,第⼀次使⽤v1版本,后组逐渐升级到v2与v3,测试镜像版本升级与回滚操作

 

deployment控制器⽀持两种更新策略:默认为滚动更新

1.滚动更新(rolling update):

滚动更新是默认的更新策略,滚动更新是基于新版本镜像创建新版本pod,然后删除⼀部分旧版本pod,然后再创建 新版本pod,再删除⼀部分旧版本pod,直到就版本pod删除完成,滚动更新优势是在升级过程当中不会导致服务不可 ⽤,缺点是升级过程中会导致两个版本在短时间内会并存。

具体升级过程是在执⾏更新操作后k8s会再创建⼀个新版本的ReplicaSet控制器,在删除旧版本的ReplicaSet 制器下的pod的同时会在新版本的ReplicaSet控制器下创建新的pod,直到旧版本的pod全部被删除完后再把就版本的 ReplicaSet控制器也回收掉。

在执⾏滚动更新的同时,为了保证服务的可⽤性,当前控制器内不可⽤的pod(pod需要拉取镜像执⾏创建和执⾏探针 探测期间是不可⽤的)不能超出⼀定范围,因为需要⾄少保留⼀定数量的pod以保证服务可以被客户端正常访问,可以通 过以下参数指定:    #kubectl  explain  deployment.spec.strategy

deployment.spec.strategy.rollingUpdate.maxSurge #指定在升级期间pod总数可以超出定义好的期望的 pod数的个数或者百分⽐,默认为25%,如果设置为10%,假如当前是100个pod,那么升级时最多将创建110个pod即额 外有10%的pod临时会超出当前(replicas)指定的副本数限制。

deployment.spec.strategy.rollingUpdate.maxUnavailable #指定在升级期间最⼤不可⽤的pod数,可 以是整数或者当前pod的百分⽐,默认是25%,假如当前是100个pod,那么升级时最多可以有25个(25%)pod不可⽤即 还要75个(75%)pod是可⽤的。

#注意:以上两个值不能同时为0,如果maxUnavailable最⼤不可⽤pod为0,maxSurge超出pod数也为0,那么将 会导致pod⽆法进⾏滚动更新。

2.重建更新(recreate):

先删除现有的pod,然后基于新版本的镜像重建,优势是同时只有⼀个版本在线,不会产⽣多版本在线问题,缺点是 pod删除后到pod重建成功中间的时间会导致服务⽆法访问,因此较少使⽤。

 


 

4.5.1 :升级到镜像到指定版本:

 

# kubectl apply -f nginx.yaml --record=true #v1版本,  --record=true为记录执⾏的kubectl

#镜像更新命令格式为:

# kubectl set image  deployment/deployment-name containers-name=image -n namespace

 

#V2

#  kubectl set image  deployment/linux36-nginx-deployment   linux36-nginx-

container=harbor.magedu.net/linux36/nginx-web1:v2  -n linux36

deployment.extensions/linux36-nginx-deployment image updated

 

#V3

#  kubectl set image  deployment/linux36-nginx-deployment   linux36-nginx-

container=harbor.magedu.net/linux36/nginx-web1:v3  -n linux36

deployment.extensions/linux36-nginx-deployment image updated

4.5.2:查看历史版本信息:

 

查看历史版本信息:

# kubectl  rollout history deployment/linux36-nginx-deployment -n linux36

deployment.extensions/linux36-nginx-deployment

CHANGE-CAUSE

kubectl apply --filename=nginx.yaml --record=true

kubectl apply --filename=nginx.yaml --record=true

kubectl apply --filename=nginx.yaml --record=true

4.5.3:回滚到上⼀个版本:

 

4.5.4:回滚到指定版本:

 


 

 

 

4.6:配置主机为封锁状态且不参与调度:

 

# kubectl   --help | grep cordon #警戒线

cordon         Mark node as unschedulable #标记为警戒,即不参加pod调度

uncordon       Mark node as schedulable #去掉警戒,即参加pod

#设置 192.168.7.110不参加调度

root@k8s-master1:/opt/k8s-data/yaml/linux36/nginx#  kubectl  cordon 192.168.7.110

node/192.168.7.110 cordoned

root@k8s-master1:/opt/k8s-data/yaml/linux36/nginx# kubectl  get node

 

NAME

STATUS

ROLES

AGE

VERSION

192.168.7.101

Ready,SchedulingDisabled

master

23d

v1.13.5

192.168.7.102

Ready,SchedulingDisabled

master

23d

v1.13.5

192.168.7.110

Ready,SchedulingDisabled

node

23d

v1.13.5

192.168.7.111

Ready

node

23d

v1.13.5

#设 192.168.7.110参加调度

root@k8s-master1:/opt/k8s-data/yaml/linux36/nginx#  kubectl  uncordon 192.168.7.110

node/192.168.7.110 uncordoned

root@k8s-master1:/opt/k8s-data/yaml/linux36/nginx# kubectl  get node

 

NAME

STATUS

ROLES

AGE

VERSION

192.168.7.101

Ready,SchedulingDisabled

master

23d

v1.13.5

192.168.7.102

Ready,SchedulingDisabled

master

23d

v1.13.5

192.168.7.110

Ready

node

23d

v1.13.5

192.168.7.111

Ready

node

23d

v1.13.5

 

4.7:从etcd删除pod                                                               

适⽤于⾃动化场景

4.7.1:查看和namespace相关的数据:

 


 

 

 

4.7.2:从etcd查看具体某个对象的数据:

 

 

4.7.3:删除etcd指定资源:

 

 

 

五:持续集成与部署                                             


 

 

 

5.1jenkins环境准备:                                                             

java配置:

 

root@s4:/usr/local/src# tar xvf jdk-8u192-linux-x64.tar.gz

root@s4:/usr/local/src# ln  -sv /usr/local/src/jdk1.8.0_192 /usr/local/jdk

root@s4:~# vim /etc/profile

export JAVA_HOME=/usr/local/jdk

export JRE_HOME=$JAVA_HOME/jre

export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH

export CLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:.

 

root@s4:~# source  /etc/profile

root@s4:~# java -version

java version "1.8.0_192"

Java(TM) SE Runtime Environment (build 1.8.0_192-b12)

Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)

 

root@s4:~# apt install daemon

root@s4:~# dpkg -i jenkins_2.138.4_all.deb

5.2gitlab环境准备:                                                                


 

root@k8s-ha1:~# cat  /root/scripts/linux36-ningx-deploy.sh

#!/bin/bash

#Author: ZhangShiJie

#Date: 2019-08-03

#Version: v1

 

#记录脚本开始执⾏时间

starttime=`date +'%Y-%m-%d %H:%M:%S'`

#变量

SHELL_DIR="/root/scripts"

SHELL_NAME="$0"

K8S_CONTROLLER1="192.168.7.101"

K8S_CONTROLLER2="192.168.7.102"

DATE=`date +%Y-%m-%d_%H_%M_%S`

METHOD=$1

Branch=$2

 

if test -z $Branch;then

Branch=develop

fi

 

 

function Code_Clone(){

Git_URL="git@172.20.100.1:linux36/app1.git"

DIR_NAME=`echo ${Git_URL} |awk -F "/" '{print $2}' | awk -F "." '{print $1}'`

DATA_DIR="/data/gitdata/linux36"

Git_Dir="${DATA_DIR}/${DIR_NAME}"

cd ${DATA_DIR} &&  echo "即将清空上⼀版本代码并获取当前分⽀最新代码" && sleep 1 && rm -rf

${DIR_NAME}

echo "即将开始从分⽀${Branch} 获取代码" && sleep 1

git clone -b ${Branch} ${Git_URL}

echo "分⽀${Branch} 克隆完成,即将进⾏代码编译!" && sleep 1

#cd ${Git_Dir} && mvn clean package

#echo "代码编译完成,即将开始将IP地址等信息替换为测试环境"

#####################################################

sleep 1

cd ${Git_Dir}

tar czf ${DIR_NAME}.tar.gz  ./*

}

#将打包好的压缩⽂件拷⻉到k8s 控制端服务器

function Copy_File(){

echo "压缩⽂件打包完成,即将拷⻉到k8s 控制端服务器${K8S_CONTROLLER1}" && sleep 1


 

scp ${Git_Dir}/${DIR_NAME}.tar.gz root@${K8S_CONTROLLER1}:/opt/k8s-

data/dockerfile/linux36/nginx/

echo "压缩⽂件拷⻉完成 ,服务器${K8S_CONTROLLER1}即将开始制作Docker 镜像!" && sleep 1 }

#到控制端执⾏脚本制作并上传镜像

function Make_Image(){

echo "开始制作Docker镜像并上传到Harbor服务器" && sleep 1

ssh root@${K8S_CONTROLLER1} "cd /opt/k8s-data/dockerfile/linux36/nginx  && bash

build-command.sh ${DATE}"

echo "Docker镜像制作完成并已经上传到harbor服务器" && sleep 1

}

#到控制端更新k8s yaml⽂件中的镜像版本号 ,从⽽保持yaml⽂件中的镜像版本号和k8s中版本号⼀致 function Update_k8s_yaml(){

echo "即将更新k8s yaml⽂件中镜像版本" && sleep 1

ssh root@${K8S_CONTROLLER1} "cd /opt/k8s-data/yaml/linux36/nginx  && sed -i 's/image:

harbor.magedu.*/image: harbor.magedu.net\/linux36\/nginx-web1:${DATE}/g' nginx.yaml"

echo "k8s yaml⽂件镜像版本更新完 ,即将开始更新容器中镜像版本" && sleep 1

}

#到控制端更新k8s中容器的版本号 ,有两种更新办法,⼀是指定镜像版本更新,⼆是apply执⾏修改过的yaml⽂件 function Update_k8s_container(){

#第⼀种⽅法

ssh root@${K8S_CONTROLLER1} "kubectl set image deployment/linux36-nginx-deployment

linux36-nginx-container=harbor.magedu.net/linux36/nginx-web1:${DATE} -n linux36"

#第⼆种⽅法 ,推荐使⽤第⼀种

#ssh root@${K8S_CONTROLLER1} "cd /opt/k8s-data/yaml/web-test/tomcat-app1 && kubectl

apply -f web-test.yam --record"

echo "k8s 镜像更新完成" && sleep 1

echo "当前业务镜像版本 : harbor.magedu.net/linux36/nginx-web1:${DATE}"

#计算脚本累计执⾏时间,如果不需要的话可以去掉下⾯四⾏

endtime=`date +'%Y-%m-%d %H:%M:%S'`

start_seconds=$(date --date="$starttime" +%s);

end_seconds=$(date --date="$endtime" +%s);

echo "本次业务镜像更新总计耗时:  "$((end_seconds-start_seconds))"s"

}

#基于k8s 内置版本管理回滚到上⼀个版本

function rollback_last_version(){

echo "即将回滚之上⼀个版本"

ssh root@${K8S_CONTROLLER1}  "kubectl rollout undo deployment/linux36-nginx-

deployment  -n linux36"

sleep 1

echo "已执⾏回滚⾄上⼀个版本"

}

#使⽤帮助

usage(){


 

 

 

 

 

六:容器监控与报警:

容器监控的实现⽅对⽐虚拟机或者物理机来说⽐⼤的区别,⽐如容器在k8s环境中可以任意横向扩容与缩容,那 么就需要监控服务能够⾃动对新创建的容器进⾏监控,当容器删除后⼜能够及时的从监控服务中删除,⽽传统的

zabbix的监控⽅式需要在每⼀个容器中安装启动agent,并且在容器⾃动发现注册及模板关联⽅⾯并没有⽐较好的 实现⽅式。

6.1:  Prometheus:

k8s的早期版本基于组件heapster实现对pod和node节点的监控功能,但是从k8s 1.8版本开始使⽤metrics API 的⽅式监控,并在1.11版本 正式将heapster替换,后期的k8s监控主要是通过metrics Server提供核⼼监控指标, ⽐如Node节点的CPU和内存使⽤率,其他的监控交由另外⼀个组件Prometheus 完成。

6.1.1:  prometheus简介:

https://prometheus.io/docs/ #官⽅⽂档

https://github.com/prometheus #github地址                                                                                                      Prometheus是基于go语⾔开发的⼀套开源的监控、报警和时间序列数据库的组合,是由SoundCloud公司开发的 开源监控系统,Prometheus于2016年加⼊CNCF  ( Cloud Native Computing Foundation,云原⽣计算基⾦会)  ,是  CNCF继kubernetes 之后毕业的第⼆个项⽬,  prometheus在容器和微服务领域中得到了⼴泛的应⽤,其特点主要 如下:


 

 

 

使⽤key-value的多维度格式保存数据

数据不使⽤MySQL这样的传统数据库,⽽是使⽤时序数据库,⽬前是使⽤的TSDB

⽀持第三⽅dashboard实现更⾼的图形界⾯,如grafana(Grafana 2.5.0版本及以上)

功能组件化

不需要依赖存储,数据可以本地保存也可以远程保存

服务⾃动化发现

强⼤的数据查询语句功(PromQL,Prometheus Query Language)

https://www.aliyun.com/product/hitsdb  #阿⾥云TSDB简介

6.1.2:  prometheus系统架构图:

 

prometheus server:主服务,接受外部http请求,收集、存储与查询数据等

prometheus targets: 静态收集的⽬标服务数据

service discovery:动态发现服务

prometheus alerting:报警通知

push gateway:数据收集代理服务器(类似于zabbix proxy)

data visualization and export    数据可视化与数据导出(访问客户端)

 

https://songjiayang.gitbooks.io/prometheus/content/promql/summary.html #ProQL简介

6.1.3:  prometheus 安装⽅式:

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

#kubectl  port-forward --help

# kubectl --namespace monitoring port-forward --address 0.0.0.0 svc/prometheus-k8s

9090:9090

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

#kubectl --namespace monitoring port-forward --address 0.0.0.0 svc/grafana 3000:3000


 

 

 

NodePort暴露服务:

grafana:

 

# pwd

/root/kube-prometheus/manifests

 

# vim grafana-service.yaml

apiVersion: v1

kind: Service

metadata:

labels:

app: grafana

name: grafana

namespace: monitoring

spec:

type: NodePort

ports:

- name: http

port: 3000

targetPort: http

nodePort: 33000

selector:

app: grafana

# kubectl apply  -f  grafana-service.yaml

 

 


 

 

 

6.1.3.1 :⼆进制⽅式安装:

 

# pwd

/usr/local/src

 

# tar xvf prometheus-2.24.1.linux-amd64.tar.gz

# ln -sv /apps/prometheus-2.24.1.linux-amd64 /apps/prometheus

'/apps/prometheus' -> '/apps/prometheus-2.24.1.linux-amd64'

# cd /apps/prometheus

# ll

prometheus.yml #配置⽂件

prometheus #prometheus服务可执⾏程序

promtool  #测试⼯具,⽤于检测配置prometheus配置⽂件、检测metrics数据等

./promtool check config prometheus.yml

Checking prometheus.yml

SUCCESS: 0 rule files found

6.1.3.2 :创建prometheus启动脚本:


 

 

 

# vim /etc/systemd/system/prometheus.service

[Unit]

Description=Prometheus Server

Documentation=https://prometheus.io/docs/introduction/overview/

After=network.target

 

[Service]

Restart=on-failure

WorkingDirectory=/apps/prometheus/

ExecStart=/apps/prometheus/prometheus   --config.file=/apps/prometheus/prometheus.yml

 

[Install]

WantedBy=multi-user.target

6.1.3.3 :启动prometheus服务:

 

6.1.3.4 :访问prometheus web界面:

 


 

6.1.4:  node exporter:

各node节点安装node_exporter,⽤于收集各k8s node节点上的监控指标数据,默认监听端⼝为9100

6.1.4.1 :⼆进制⽅式安装node exporter:

 

# mkdir  /apps

# cd /apps/

 

# tar xvf node_exporter-1.0.1.linux-amd64.tar.gz

# ln -sv /apps/node_exporter-1.0.1.linux-amd64 /apps/node_exporter

# cd /apps/node_exporter

node_exporter #可执⾏程序

6.1.4.2 :创建node exporter启动脚本:

 

# vim   /etc/systemd/system/node-exporter.service

[Unit]

Description=Prometheus Node Exporter

After=network.target

 

[Service]

ExecStart=/apps/node_exporter/node_exporter

 

[Install]

WantedBy=multi-user.target

6.1.4.3 :启动node exporter服务:

 

6.1.4.4 :访问node exporter web界⾯:

 


 

 

 

6.1.5:  prometheus采集node 指标数据:

配置prometheus通过node exporter采集 监控指标数据

6.1.5.1 :prometheus默认配置⽂件:

 


 

 

 

6.1.5.2 :prometheus收集node数据:

 

root@prometheus-server:~# cat  /apps/prometheus/prometheus.yml

# my global config

global:

scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is

every 1 minute.

evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1

minute.

# scrape_timeout is set to the global default (10s).

 

# Alertmanager configuration

alerting:

alertmanagers:

- static_configs:

- targets:

# - alertmanager:9093

 

# Load rules once and periodically evaluate them according to the global

'evaluation_interval'.

rule_files:

# - "first_rules.yml"

# - "second_rules.yml"

 

# A scrape configuration containing exactly one endpoint to scrape:

# Here it's Prometheus itself.

scrape_configs:

# The job name is added as a label `job=<job_name>` to any timeseries scraped from

this config.

- job_name: 'prometheus'

 

# metrics_path defaults to '/metrics'

# scheme defaults to 'http'.

 

static_configs:

- targets: [ 'localhost:9090']

- job_name: 'promethues-node'

static_configs:

- targets: [ '172.31.7.111:9100', '172.31.7.112:9100']


 

 

 

6.1.5.2 :重启prometheus服务:

 

6.1.5.3 :prometheus验证node节点状态:

 

6.1.5.4 :prometheus验证node节点监控数据:


 

 

 

6.1.6:  PromQL简介:

Prometheus提供⼀个函数式的表达式语⾔PromQL (Prometheus Query Language),可以使⽤户实时地查找和聚 合时间序列数据,表达式计算结果可以在图表中展示,也可以在Prometheus表达式浏览器中以表格形式展示,或 者作为数据源, 以HTTP API的⽅式提供给外部系统使⽤

6.1.6.1:  PromQL基本查询:

 


 

 

 

6.1.6.2:  PromQL数据类型:

 

瞬时向量 (instant vector):是⼀组时间序列,每个时间序列包含单个数据样本,⽐如                                             node_memory_MemTotal_bytes查询当前剩余内存就是⼀个瞬时向量,该表达式的返回值中只会包含该时间序列中的 最新的⼀个样本值,⽽相应的这样的表达式称之为瞬时向量表达式。

范围向量(range vector):是指在任何⼀个时间范围内,抓取的所有度量指标数据 . ⽐如最近⼀天的⽹卡流量趋势图。 标量 (scalar):是⼀个浮点数类型的数据值,使⽤node_load1获取到时⼀个瞬时向量,但是可⽤使⽤内置函数         scalar()将瞬时向量转换为标量。

字符串 (string):字符串类型的数据,⽬前使⽤较少

6.1.6.3:  PromQL匹配器:

=  :选择与提供的字符串完全相同的标签。

!= :选择与提供的字符串不相同的标签。

=~ :选择正则表达式与提供的字符串(或⼦字符串)相匹配的标签。

!~ :选择正则表达式与提供的字符串(或⼦字符串)不匹配的标签。

 

#查询格式<metric name>{<label name>=<label value>, ...}

node_load1{instance="172.31.7.111:9100"}

node_load1{job="promethues-node"}

 

node_load1{job="promethues-node",instance="172.31.7.111:9100"}

node_load1{job="promethues-node",instance!="172.31.7.111:9100"}

6.1.6.4:  PromQL时间范围:

 

s - 秒

m - 分钟

h - ⼩时

d - 

w - 周

y - 年

node_memory_MemTotal_bytes{} # 瞬时向量表达式,选择当前最新的数据                                     node_memory_MemTotal_bytes{}[5m] # 区间向量表达式,选择以当前时间为基准,  5分钟内的数据 node_memory_MemTotal_bytes{instance="172.31.7.111:9100"}[5m]

 


 

 

 

6.1.6.5:  PromQL运算符:

 

+ 加法

- 减法

* 乘法 / 除法 % 模   ^ 幂等

node_memory_MemFree_bytes/1024/1024 #将内存进⾏单位转换                                                                     node_disk_read_bytes_total{device="sda"} + node_disk_written_bytes_total{device="sda"}

#计算磁盘每秒读写数据量

 


 

6.1.6.6:  PromQL聚合运算:

 

sum (求和 )

min (最⼩ )

max (最⼤ )

avg (平均 )

stddev (标准差)

stdvar (标准差异)

count (计数 )

count_values (  value 进⾏计数 )

bottomk (样本值最⼩的  k 个元素 )

topk (样本值最⼤的k个元素 )

quantile (分布统计)

max(node_memory_MemFree_bytes) #获5分钟内的最⼤值

sum(http_requests_total) #计算http_requests_total最近的请求总量

 

6.2 Grafana

https://grafana.com/docs/ #官⽅安装⽂档

调⽤prometheus的数据,进⾏更专业的可视化

6.2.1:安装grafana:

安装版本:   v7.3.7

 


 

6.2.2:配置⽂件:

 

# vim /etc/grafana/grafana.ini

[server]

# Protocol (http, https, socket)

protocol = http

 

# The ip address to bind to, empty will bind to all interfaces

http_addr = 0.0.0.0

 

# The http port  to use

http_port = 3000

6.2.3:启动grafana:

 

6.2.4 :grafana web界⾯:

6.2.4.1 :登录界⾯:

 


 

6.2.4.2 :添加prometheus数据源:

 

 

 

 


 

 

 


 

 

 

 

 

6.4.3:  import模板:

导⼊模板查看web

6.4.3.1 :模板下载地址:

模板可以在左侧栏匹配或搜索相关名称


 

 

 

6.4.3.2 :模板详细信息:

 

 

 


 

6.4.3.3 :下载模板:

 

6.4.3.4 :通过模板ID导入:

 


 

6.4.3.5 :确认模板信息:

 

6.4.3.6 :验证图形信息:

饼图插件未安装,需要提前安装

https://grafana.com/grafana/plugins/grafana-piechart-panel

 

 

在线安装:

# grafana-cli plugins install grafana-piechart-panel

 

离线安装:

# pwd

/var/lib/grafana/plugins

 

# unzip grafana-piechart-panel-v1.3.8-0-g4f34110.zip

# mv grafana-piechart-panel-4f34110 grafana-piechart-panel

# systemctl  restart grafana-server

未安装饼图插件:


 

 

 

已安装饼图插件:

 

其他监控项图形:

 


cadvisor由⾕歌开源,  cadvisor不仅可以搜集⼀台机器上所有运⾏的容器信息,还提供基础查询界⾯和http接⼝, ⽅便其他组件如Prometheus进⾏数据抓取,  cAdvisor可以对节点机器上的资源及容器进⾏实时监控和性能数据 集,包括CPU使⽤情况、内存使⽤情况、⽹络吞吐量及⽂件系统使⽤情况。

k8s 1.12之前cadvisor集成在node节点的上kubelet服务中,从1.12版本开始分离为两个组件,因此需要在node节 点单独部署cadvisor。

https://github.com/google/cadvisor

6.3.1 :cadvisor镜像准备:

 

# docker load -i  cadvisor-v0.38.7.tar.gz

# docker tag gcr.io/cadvisor/cadvisor:v0.38.7

harbor.magedu.net/linux46/cadvisor:v0.38.7

# docker push harbor.magedu.net/linux46/cadvisor:v0.38.7

6.3.2:启动cadvisor容器:

 

# docker run -it -d  \

--volume=/:/rootfs:ro \

--volume=/var/run:/var/run:ro \

--volume=/sys:/sys:ro \

--volume=/var/lib/docker/:/var/lib/docker:ro \

--volume=/dev/disk/:/dev/disk:ro \

--publish=8080:8080 \

--detach=true \

--name=cadvisor \

--privileged \

--device=/dev/kmsg \

harbor.magedu.net/linux46/cadvisor:v0.38.7

6.3.3:验证cadvisor web界⾯:

访问node节点的cadvisor监听端⼝:  http://192.168.7.110:8080/


 

 

 

6.3.4:  prometheus采集cadvisor数据:

 


 

 

 

6.3.5:重启prometheus:

 

6.3.6:验证prometheus数据:

 

6.3.7 :grafana添加pod监控模板:

395  893 容器模ID

395模板:


 

 

 

893模板:

修改模板变量

修改模板key的名称

 

 


 

 

 

6.4  prometheus报警设置:                                                     

prometheus触发⼀条告警的过程:

prometheus--->触发阈值--->超出持续时间--->alertmanager--->分组|抑制|静默--->媒体类型--->邮件|钉钉|微信 等。

 

 

6.4.1:下载并报警组件alertmanager:

 


 

 

 

6.4.2:配置alertmanager:

https://prometheus.io/docs/alerting/configuration/ #官⽅配置⽂档

 

global:

smtp_from:      #发件⼈邮箱地址

smtp_smarthost: #邮箱smtp地址。

smtp_auth_username:  #发件⼈的登陆⽤户名,默认和发件⼈地址⼀致。

smtp_auth_password:  #发件⼈的登陆密码,有时候是授权码。

smtp_require_tls:    #是否需要tls协议。默认是true。

wechart_api_url:     #企业微信API 地址。

wechart_api_secret    #企业微信API secret

wechat_api_corp_id:  #企业微信corp id信息。

resolve_timeout:  #在指定时间内没有产⽣新的事件就发送恢复通知

 

 

 

 


 

 

 

6.4.3:启动alertmanager服务:

 

# systemctl  restart  alertmanager.service

#验证alertmanager的9093端⼝已经监听

# lsof  -i:9093

COMMAND      PID USER

alertmana 127083 root

alertmanager dashboard截图

 


 

6.4.4:配置prometheus报警规则:

 

# cd  /usr/local/prometheus

 

# vim prometheus.yml

# Alertmanager configuration

alerting:

alertmanagers:

- static_configs:

- targets:

- 192.168.7.102:9093  #alertmanager地址

# Load rules once and periodically evaluate them according to the global

'evaluation_interval'.

rule_files:

- "/apps/prometheus/rule.yml" #指定规则⽂件

# - "second_rules.yml"

6.4.5:创建报警规则⽂件:

 


 

 

 

6.4.6:报警规则验证:

 

# pwd

/usr/local/prometheus

#验证报警规则设置:

#  ./promtool check rules  rule-linux36.yml  #监测rule规则⽂件是否正确

Checking rule-linux36.yml

SUCCESS: 3 rules found

6.4.7:重启prometheus:

 

6.4.8:验证报警规则匹配:

 


 

6.4.9:  prometheus⾸⻚状态:

 

 

6.4.10:  prometheus web界⾯验证报警规则:

status-rules

 


 

6.4.11 :验证收到的报警邮件:

 

6.5  prometheus监控haproxy                                              

6.5.1:部署haproxy_exporter:

 

# pwd

/usr/local/src

 

# tar xvf haproxy_exporter-0.9.0.linux-amd64.tar.gz

# ln -sv /usr/local/src/haproxy_exporter-0.9.0.linux-amd64 /usr/local/haproxy_exporter

 

# cd /usr/local/haproxy_exporter

# ./haproxy_exporter --haproxy.scrape-uri=unix:/run/haproxy/admin.sock

# ./haproxy_exporter --haproxy.scrape-

uri="http://haadmin:q1w2e3r4ys@127.0.0.1:9999/haproxy-status;csv" &

6.5.2:验证web界⾯数据:


 

 

 

6.5.3:  prometheus server端添加haproxy数据采集:

 

# vim /usr/local/prometheus/prometheus.yml

 

# cd /usr/local/prometheus/

#  grep -v "#"  prometheus.yml  | grep -v "^$"

global:

alerting:

alertmanagers:

- static_configs:

- targets: ["192.168.7.102:9093"]

rule_files:

- "/usr/local/prometheus/rule-linux36.yml"

scrape_configs:

- job_name: 'prometheus'

static_configs:

- targets: [ 'localhost:9090']

- job_name: 'promethues-node'

static_configs:

- targets: [ '192.168.7.110:9100', '192.168.7.111:9100']

- job_name: 'prometheus-containers'

static_configs:

- targets: ["192.168.7.110:8080","192.168.7.111:8080"]

- job_name: 'prometheus-haproxy'

static_configs:

- targets: ["192.168.7.108:9101"]

 


 

6.5.4:重启prometheus:

 

6.5.5 :grafana添加模板:

367 2428

 

6.5.6:验证haproxy监控数据:

 

6.6  prometheus监控nginx                                                  

通过prometheus监控nginx

需要在编译安装nginx的时候添加nginx-module-vts模块,  github地址:  https://github.com/vozlt/nginx-module- vts


 

6.6.1:编译安装nginx:

 

# git clone https://github.com/vozlt/nginx-module-vts.git

# wget http://nginx.org/download/nginx-1.18.0.tar.gz

# tar xvf nginx-1.18.0.tar.gz

# cd nginx-1.18.0/

# ./configure --prefix=/apps/nginx --add-module=/usr/local//src/nginx-module-vts/

# cd /apps/nginx/conf/

 

# vim nginx.conf

#gzip  on;

vhost_traffic_status_zone; #

server {

listen       80;

server_name  localhost;

 

#charset koi8-r;

 

#access_log  logs/host.access.log  main;

 

location / {

root   html;

index  index.html index.htm;

}

 

location /status {

vhost_traffic_status_display;

vhost_traffic_status_display_format html;

}

}

 

root@grafana-server:/apps/nginx/conf# /apps/nginx/sbin/nginx  -t

nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok

nginx: configuration file /apps/nginx/conf/nginx.conf test is successful

root@grafana-server:/apps/nginx/conf# /apps/nginx/sbin/nginx

6.6.2:验证状态⻚:


 

 

 

6.6.3:安装nginx exporter:

 

# wget https://github.com/hnlq715/nginx-vts-exporter/releases/download/v0.10.3/nginx-

vts-exporter-0.10.3.linux-amd64.tar.gz

# tar xvf nginx-vts-exporter-0.10.3.linux-amd64.tar.gz

# ln -sv /apps/nginx-vts-exporter-0.10.3.linux-amd64 /apps/nginx-vts-exporter

'/apps/nginx-vts-exporter' -> '/apps/nginx-vts-exporter-0.10.3.linux-amd64'

 

# cd /apps/nginx-vts-exporter

# ./nginx-vts-exporter  -nginx.scrape_uri http://172.31.7.162/status/format/json

6.6.4:验证nginx exporter数据:


 

 

 

 

 

6.6.5:  prometheus配置:

 


 

 

 

 

 

6.6.6 :grafana关联模板:

https://grafana.com/grafana/dashboards/2949

 

 

 

 

 

https://developers.dingtalk.com/document/app/how-to-call-apis

https://github.com/timonwong/prometheus-webhook-dingtalk


 

 

 

 

 

curl 'https://oapi.dingtalk.com/robot/send?

access_token=ba217ad9d1b70a9c8b10a88f46bb5e0e04fbcfd36bf80d22ee7cd99c79648dad' \

-H 'Content-Type: application/json' \

-d '{"msgtype": "text",

"text": {

"content": "业务运维报警机器⼈ -Node01 is down"

}

} '

 

 

七.k8s:实战案例:

http://www.uml.org.cn/yunjisuan/201703162.asp?artid=19131 #京东从openstack切换为K8S

7.1  K8S⾼可⽤:                                                                       

基于HAProxy+Keepalived实现⾼可⽤k8s集群环境、实现K8S版本升级、  calico与flannel⽹络通信、  kube DNS与 CoreDNS 、Dashboard。

7.1.1:⾼可⽤K8S基础环境:

 


 

7.1.2:当前运⾏状态:

 

7.2:动静分离web站点:

以下服务要求全部运⾏在K8S环境内,主要介绍在k8s中运⾏⽬前⽐较常⻅的主流服务和架构,如基于                  Nginx+Tomcat的动静分离架构、基于PVC实现的Zookeeper集群和Redis服务,基于PVC+StatefulSet实现的       MySQL主从架构,运⾏java应⽤,  K8S中基于Nginx+PHP+MySQL实现的WordPress的web站点,如何在k8s中基

于Zookeeper运⾏微服务等,以及K8S的CI与CD、⽇志收集分析展示与prometheus+grafana实现pod监控与报警 等。

7.2.1:  Nginx+Tomcat实动静分离web站点:

基于Nginx+Tomcat+NFS实现通过域名转发动态请求到Tomcat Pod的动静分离架构,要求能够通过负载均衡的VIP 访问到k8s集群中运⾏的Nginx+Tomcat+NFS中的web⻚⾯。

 

 

 

 


 

keepalive_timeout  65;

upstream  tomcat_webserver {

server  linux35-tomcat-app1-spec.linux35.svc.linux35.local:80;

server  linux35-tomcat-app2-spec.linux35.svc.linux35.local:80;

}

server {

listen       80;

server_name  localhost;

location / {

root   html;

index  index.html index.htm;

}

location /webapp {

root   html;

index  index.html index.htm;

}

location /myapp {

proxy_pass  http://tomcat_webserver;

proxy_set_header   Host    $host;

proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header X-Real-IP $remote_addr;

}


error_page

location =

root

}

}

}

 

500 502

/50x.html

html;

 

503 504  /50x.html;

{


 

 

 

 

 

7.3  PVPVC实战案例:                                                            

默认情况下容器中的磁盘⽂件是⾮持久化的,对于运⾏在容器中的应⽤来说⾯临两个问题,第⼀:当容器挂掉 kubelet将重启启动它时,⽂件将会丢失;第⼆:当Pod中同时运⾏多个容器,容器之间需要共享⽂件时,       Kubernetes的Volume解决了这两个问题。

https://v1-14.docs.kubernetes.io/zh/docs/concepts/storage/  #官⽅⽂档


 

 

 

PersistentVolume ( PV)是集群中已由管理员配置的⼀段⽹络存储,集群中的存储资源就像⼀个node节点是⼀个集 群资源,  PV是诸如卷之类的卷插件,但是具有独⽴于使⽤ PV的任何单个pod的⽣命周期,    API对象捕获存储的实现细 节,即NFS,  iSCSI或云提供商特定的存储系统,  PV是由管理员添加的的⼀个存储的描述,是⼀个全局资源即不⾪属于

任何namespace,包含存储的类型,存储的⼤⼩和访问模式等,它的⽣命周期独⽴于Pod,例如当使⽤它的Pod销毁时 对PV没有影响。

PersistentVolumeClaim ( PVC)是⽤户存储的请求,它类似于pod,Pod消耗节点资源,  PVC消耗存储资源,    就像 pod可以请求特定级别的资源(CPU和内存),  PVC是namespace中的资源,可以设置特定的空间⼤⼩和访问模式。

kubernetes 1.0版本开始⽀持PersistentVolumePersistentVolumeClaim

PV是对底层⽹络存储的抽象,即将⽹络存储定义为⼀种存储资源,将⼀个整体的存储资源拆分成多份后给不同的业务使

⽤。

PVC是对PV资源的申请调⽤,就像POD消费node节点资源⼀样 ,pod是通过PVC将数据保存⾄PVPV在保存⾄存储。

 

PersistentVolume参数:

 


 

 

 

官⽅提供的基于各后端存储创建的PV⽀持的访问模式

https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options

 

PersistentVolumeClaim创建参数:

 


 

 

 

7.3.1:实战案例之zookeeper集群:

基于PV和PVC作为后端存储,实现zookeeper集群

7.3.1.1 :下载JDK镜像:

 

7.3.1.2 :zookeeper镜像准备:

https://www.apache.org/dist/zookeeper  #官⽅程序包下载官⽅⽹址

7.3.1.2.1:构建zookeeper镜像:

 

 

7.3.1.2.2:测试zookeeper镜像:

 


 

 

 

7.3.1.2.3:测试客户端连接zookeeper:

 

 

 

 

7.3.1.3 :k8s 运⾏zookeeper服务:

通过yaml⽂件将zookeeper集群服务运⾏k8s环境

7.3.1.3.1 :yaml⽂件准备:

yaml⽬录结构


 

 

 

# pwd

/opt/k8s-data/yaml/linux36/zookeeper

 

# tree

.

├──  pv

│      ├──  zookeeper-persistentvolumeclaim.yaml

│      L──  zookeeper-persistentvolume.yaml

L──  zookeeper.yaml

1 directory, 3 files

7.3.1.3.2:创建PV:

 

7.3.1.3.3:验证PV:

 

7.3.1.3.4:创建PVC:

 

# kubectl  apply  -f  zookeeper-persistentvolumeclaim.yaml

persistentvolumeclaim/zookeeper-datadir-pvc-1 created

persistentvolumeclaim/zookeeper-datadir-pvc-2 created

persistentvolumeclaim/zookeeper-datadir-pvc-3 created

7.3.1.3.5:验证PVC:

 

7.3.1.3.6 dashborad 验证存储卷:


 

 

 

7.3.1.3.7:运行zookeeper集群:

 

# pwd

/opt/k8s-data/yaml/linux36/zookeeper

 

# kubectl  apply  -f zookeeper.yaml

service/zookeeper created

service/zookeeper1 created

service/zookeeper2 created

service/zookeeper3 created

deployment.extensions/zookeeper1

deployment.extensions/zookeeper2

deployment.extensions/zookeeper3

7.3.1.3.8:验证zookeeper集群:

 

# kubectl  get pod -n linux36

NAME

。。。。。。。。。。。

zookeeper1-5f458745bf-lxsww

zookeeper2-5844958588-9gvjh

zookeeper3-7b646949f-w52cr

 

# kubectl  exec -it zookeeper2-5844958588-9gvjh  sh -n linux36

 


 

 

 

 

7.3.1.3.9:验证从外部访问zookeeper:

 


 

 

 

7.3.2:实战案例之Redis 服务:

在k8s环境中运行redis服务

7.3.2.1 :构建redis镜像:

7.3.2.1.1 :镜像⽂件:

 

# pwd

/opt/k8s-data/dockerfile/linux36/redis

 

# tree

.

├──  build-command.sh

├──  Dockerfile

├──  redis-4.0.14.tar.gz

├──  redis.conf

L──  run_redis.sh

0 directories, 5 file

7.3.2.1.2:构建镜像:

 


 

 

 

7.3.2.1.3:测试redis 镜像:

 

7.3.2.2 :运⾏redis服务:

基于PV/PVC保存数据,实现k8s中运⾏Redis服务

7.3.2.2.1:创建PV与PVC:

 

# pwd

/opt/k8s-data/yaml/linux36/redis/pv

 

# kubectl  apply  -f .

persistentvolume/redis-datadir-pv-1 created

persistentvolumeclaim/redis-datadir-pvc-1 created

7.3.2.2.2:验证PV与PVC:

redisPVPVC已经处于bond状态

命令⾏验证:

 


 

dashboard验证:

 

7.3.1.2.3:运⾏Redis服务:

 

# pwd

/opt/k8s-data/yaml/linux36/redis

 

# tree

.

├──  pv

│      ├──  redis-persistentvolumeclaim.yaml

│      L──  redis-persistentvolume.yaml

L  redis.yaml

1 directory, 3 files

 

# kubectl  apply  -f redis.yaml

deployment.extensions/deploy-devops-redis created

service/srv-devops-redis created

7.3.1.2.4:外部客户端访问redis:

 

 

 


 

 

 

7.3.1.2.5:验证PVC存储卷数据:

验证nfs服务器Redis的快照数据:

 

进⼊到容器⾥验证redis数据

 

 

7.3.2.2.6:验证Redis服务:

从k8s集群外的环境通过nodeport访问k8s环境中的的redis服务,或者从其他pod访问测试


 

 

 

7.3.2.2.7:验证Redis数据⾼可⽤:

删除redis的pod,然后重新创建pod验证新⽣成的pod中是否有之前的数据,可能有丢失数据的⼏率,取决于是否 开启AOF或者dump数据的功能及设置:

 

# pwd

/opt/k8s-data/yaml/linux36/redis

 

# kubectl  delete -f  redis.yaml

deployment.extensions "deploy-devops-redis" deleted

service "srv-devops-redis" deleted

 

# kubectl  apply  -f  redis.yaml

deployment.extensions/deploy-devops-redis created

service/srv-devops-redis created

然后重新验证之前的key是也就是之前的数据是否还存在

7.3.3:实战案例之MySQL 主从架构:

https://kubernetes.io/zh/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/ https://www.kubernetes.org.cn/statefulset

基于StatefulSet实现:

https://kubernetes.io/zh/docs/tasks/run-application/run-replicated-stateful-application/

Pod调度运⾏时,如果应⽤不需要任何稳定的标示、有序的部署、删除和扩展,则应该使⽤⼀组⽆状态副本的控制 器来部署应⽤,例如 Deployment  ReplicaSet更适合⽆状态服务需求,⽽StatefulSet适合管理所有有状态的服  务,⽐如MySQL 、MongoDB集群等。

基于StatefulSet 实现的MySQL ⼀主多从架构


 

 

 

 

StatefulSet本质上是Deployment的⼀种变体,在v1.9版本中已成为GA版本,它为了解决有状态服务的问题,它所 管理的Pod拥有固定的Pod名称,启停顺序,在StatefulSet中,  Pod名字称为⽹络标识(hostname),还必须要⽤到

共享存储。

在Deployment中,与之对应的服务是service,⽽在StatefulSet中与之对应的headless service,headless service,即⽆头服务,与service的区别就是它没有Cluster IP,解析它的名称时将返回该Headless Service 对应的全部Pod的Endpoint列表。

StatefulSet 特点:

-> 给每个pod分配固定且唯⼀的⽹络标识符

-> 给每个pod分配固定且持久化的外部存储

-> 对pod进⾏有序的部署和扩展

-> 对pod进有序的删除和终⽌

-> pod进有序的⾃动滚动更新

7.3.3.1 :StatefulSet的组成部分:

 


 

7.3.3.2 :镜像准备:

https://github.com/docker-library/  #github 下载地址

基础镜像准备:

 

#准备xtrabackup镜像

# docker pull registry.cn-hangzhou.aliyuncs.com/hxpdocker/xtrabackup:1.0

# docker tag registry.cn-hangzhou.aliyuncs.com/hxpdocker/xtrabackup:1.0

harbor.magedu.net/linux36xtrabackup:1.0

# docker push harbor.magedu.net/linux36/xtrabackup:1.0

#准备mysql 镜像

# docker pull mysql:5.7

# docker tag mysql:5.7 harbor.magedu.net/baseimages/mysql:5.7

# docker push harbor.magedu.net/baseimages/mysql:5.7

7.3.3.3 :创建PV:

pvc会⾃动基于PV创建,只需要有多个可⽤的PV即可,  PV数量取决于计划启动多少个mysql pod,本次创建5个 PV,也就是最多启动5个mysql pod。

 


 

 

 

7.3.3.4 :验证PV:

 

7.3.3.5 :运行mysql服务:

创建mysql pod:

 

# pwd

/opt/k8s-data/yaml/linux36/mysql

 

# ll

total 28

drwxr-xr-x 3 root root 4096 Aug  4 18:22 ./

drwxr-xr-x 7 root root 4096 Aug  4 18:19 ../

-rw-r--r-- 1 root root  364 Aug  4 17:34 mysql-configmap.yaml

-rw-r--r-- 1 root root  529 Aug  4 17:38 mysql-services.yaml

-rw-r--r-- 1 root root 5510 Aug  4 17:53 mysql-statefulset.yaml

drwxr-xr-x 2 root root 4096 Aug  4 18:20 pv/

 

# kubectl  create -f . -n linux36

configmap/mysql created

service/mysql created

service/mysql-read created

statefulset.apps/mysql created

7.3.3.6 :验证MySQL Pod状态:

 


 

7.3.3.7 :验证MySQL主从同步是否正常:

 

7.3.3.8 :⾼可⽤测试:

分别删除pod中的master与slave节点,验证MySQL服务最终能否恢复到正常状态。

7.3.3.8.1:删除MySQL Master:

 

# kubectl get pod -n linux36

STATUS

Running

Running

Running

 

# kubectl  delete pod mysql-0 -n linux36

pod "mysql-0" deleted

 


 

 

 

7.3.3.8.2:删除MySQL Slave:

 

# kubectl get pod -n linux36

STATUS

Running

Running

Running

 

# kubectl  delete pod mysql-1 -n linux36

pod "mysql-1" deleted

 

 

 

7.3.4:运⾏java应⽤:

基于java命令,运⾏java war包或jar包,本次以jenkins.war 包部署⽅式为例,且要求jenkins的数据保存⾄外部存 储(NFS或者PVC),其他java应⽤看实际需求是否需要将数据保存⾄外部存储。

7.3.4.1 :镜像⽬录⽂件:


 

 

 

# pwd

/opt/k8s-data/dockerfile/linux36/jenkins

 

# tree

.

├──  build-command.sh

├──  Dockerfile

├──  jenkins-2.164.3.war

L──  run_jenkins.sh

0 directories, 4 files

7.3.4.2 :构建Jenkins镜像:

 

 

7.3.4.3 :验证Jenkins镜像:

 


 

 

 

7.3.4.4 :创建PV/PVC:

需要两个PVC,⼀个保存jenkins的数据,⼀个保存.jenkins的数据。

 

root@k8s-ha1:/data/linux36# ll  /data/k8sdata/linux36/jenkins-data

root@k8s-ha1:/data/linux36# ll /data/k8sdata/linux36/jenkins-root-data

 

# kubectl  apply  -f pv/

persistentvolume/jenkins-datadir-pv created

persistentvolume/jenkins-root-datadir-pv created

persistentvolumeclaim/jenkins-datadir-pvc created

persistentvolumeclaim/jenkins-root-data-pvc created

7.3.4.5 :验证PV/PVC:

 

# kubectl  get pv -n linux36

NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS

jenkins-datadir-pv 100Gi   RWO   Retain    Bound

jenkins-root-datadir-pv 100Gi RWO  Retain  Bound

 

root@k8s-master1:/opt/k8s-data/yaml/linux36/jenkins# kubectl  get pvc  -n linux36

NAME           STATUS  VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE

jenkins-datadir-pv

jenkins-root-datadir-pv

7.3.4.6:yaml文件:


 

 

 

# pwd

/opt/k8s-data/yaml/linux36/jenkins

root@k8s-master1:/opt/k8s-data/yaml/linux36/jenkins# tree

.

├──  jenkins.yaml

L──  pv

├──  jenkins-persistentvolumeclaim.yaml

L──  jenkins-persistentvolume.yaml

1 directory, 3 files

7.3.4.7 :k8s运行jenkins服务:

 

# pwd

/opt/k8s-data/yaml/linux36/jenkins

 

# kubectl  apply  -f jenkins.yaml

deployment.extensions/linux36-jenkins-deployment created

service/linux36-jenkins-service created

7.3.4.8 :验证pod:

 

# kubectl  get pods -n  linux36

NAME

linux36-jenkins-deployment-74c4b55576-ssxdv

 

# kubectl  describe pods linux36-jenkins-deployment-74c4b55576-ssxdv  -n linux36

Events:

Type    Reason     Age   From                    Message

----    ------     ----  ----                    -------

Normal  Scheduled  60s   default-scheduler       Successfully assigned

linux36/linux36-jenkins-deployment-74c4b55576-ssxdv to 192.168.7.111

Normal  Pulling    58s   kubelet, 192.168.7.111  pulling image

"harbor.magedu.net/linux36/jenkins:v2.164.3"

Normal  Pulled     55s   kubelet, 192.168.7.111  Successfully pulled image

"harbor.magedu.net/linux36/jenkins:v2.164.3"

 

7.3.4.9 :验证web访问jenkins:


 

 

 

 

 

 

 

7.3.5:  k8s 示例之WordPress:

LNMP案例之基于Nginx+PHP实现WordPress博客站点,要求Nginx+PHP运⾏在同⼀个Pod的不同容器,

运⾏与default的namespace并可以通过service name增删改查数据库。

 

 

https://cn.wordpress.org/

https://cn.wordpress.org/download/releases/

wordpress-5.0.2-zh_CN.tar.gz

7.3.5.1 :准备PHP镜像:

7.3.5.1.1:官⽅PHP镜像:

https://hub.docker.com/

 

 

 

 

 

MySQL

# docker pull php:5.6.40-fpm

# docker tag php:5.6.40-fpm  harbor.magedu.net/linux36/php:5.6.40-fpm

# docker push harbor.magedu.net/linux36/php:5.6.40-fpm

 

7.3.5.1.2:⾃制PHP镜像:


 

 

 

# pwd

/opt/k8s-data/dockerfile/linux36/wordpress/php

# tree

.

├──  build-command.sh

├──  Dockerfile

├──  run_php.sh

L── www.conf

0 directories, 4 files

 

# bash build-command.sh  v1

 

7.3.5.2 :准备Nginx镜像:

 

# pwd

/opt/k8s-data/dockerfile/linux36/wordpress/nginx

 

# tree

.

├──  build-command.sh

├──  Dockerfile

├──  index.html

├──  nginx.conf

L──  run_nginx.sh

0 directories, 5 files

 

# bash build-command.sh  v1

 


 

7.3.5.3 :运⾏WordPress站点:

使⽤官⽅PHP镜像运⾏PHP环境,  WordPress⻚⾯⽂件保存在后端存储NFS服务器。

7.3.5.3.1:运⾏WordPress:

 

# pwd

/opt/k8s-data/yaml/linux36/wordpress

 

# kubectl  apply -f .

deployment.extensions/wordpress-app-deployment created

service/wordpress-app-spec created

7.3.5.3.2:创建PHP测试⻚:

准备WordPress⻚⾯⽂件并更改权限为指定⽤户

 

# pwd

/data/k8sdata/linux36/wordpress

 

# cat test.php

<?php

phpinfo();

?>

 

linux36# chown  2001.2001 wordpress/ -R

7.3.5.3.3:访问PHP测试⻚:


 

 

 

 

 

7.3.5.4 :初始化WordPress站点:

使⽤k8s中运⾏的mysql服务,作为mysql服务器

7.3.5.4.1 :k8s中MySQL创建数据库:

 

# kubectl  exec -it mysql-0 sh -n linux36

.....

mysql> CREATE DATABASE wordpress;

Query OK, 1 row affected (0.01 sec)

 

mysql>  GRANT ALL PRIVILEGES ON wordpress.* TO "wordpress"@"%"  IDENTIFIED BY

"wordpress";

Query OK, 0 rows affected, 1 warning (0.01 sec)

7.3.5.4.2 :k8s中测试MySQL连接:

 


 

 

 

7.3.5.4.3:通过web界⾯初始化数据库:

 


 

 

 

 

 

 


 

 

 

 

 

 


 

 

 

 

 

 


 

 

 

7.3.5.4.4 :WordPress数据库连接配置:

 


 

 

 

7.3.5.5 :验证k8s中mysql 数据:

分别验证k8s中MySQL主库和从库是否数据

7.3.5.5.1 :master数据:


 

 

 

7.3.5.5.2 :slave数据库:


 

 

 

 

 

7.3.6:运行dubbo服务:

运⾏dubbo⽣成者与消费者示例

dubbo 源码编译:

官⽅⽹站:  http://dubbo.apache.org/zh-cn/

 

7.3.6.1 :运行provider:

7.3.6.1.1 :准备镜像:

 


 

 

 

7.3.1.6.2:运⾏provider服务:

 

7.3.1.6.3 :zookeeper验证provider注册:

 

7.3.6.2 :运⾏consumer

7.3.6.2.1:准备consumer镜像:

 

7.3.6.2.2:运⾏consumer服务:


 

 

 

pwd

/opt/k8s-data/yaml/linux36/dubbo/consumer

 

# kubectl  apply  -f .

deployment.extensions/linux36-consumer-deployment created

service/linux36-consumer-spec created

7.3.6.2.3 :zookeeper验证消费者:

 

 

 

7.3.6.3 :运⾏dubbo admin

7.3.6.3.1 :镜像准备:

 

# pwd

/opt/k8s-data/dockerfile/linux36/dubbo/dubboadmin

 

# vim dubboadmin/WEB-INF/dubbo.properties

# zip -r  dubboadmin.war dubboadmin/*

# bash build-command.sh

 

 

 

7.3.6.3.3:运⾏服务:

 


 

 

 

 

 

当前pod运⾏状态:

 

 

 

7.4:日志收集:

实现pod中⽇志收集之⾄ELK,⾃定义字段数据格式转换、排序、基于⽇志实现pod⾃愈、⾃动扩容等 ⻅ELK ⽇志收集。

⻅ELK ⽇志收集。

https://kubernetes.io/zh/docs/concepts/cluster-administration/logging/


 

 

 

 

#cat build-command.sh

 

#!/bin/bash

#echo "nameserver 223.6.6.6" > /etc/resolv.conf

#echo "192.168.7.248 k8s-vip.example.com" >> /etc/hosts

 

/usr/share/filebeat/bin/filebeat -c /etc/filebeat/filebeat.yml -path.home

/usr/share/filebeat -path.config /etc/filebeat -path.data /var/lib/filebeat -path.logs

/var/log/filebeat  &

su - tomcat -c "/apps/tomcat/bin/catalina.sh start"

tail -f /etc/hosts

 

filebeat.inputs:

- type: log

enabled: true

paths:

- /apps/tomcat/logs/catalina.out

fields:

type: tomcat-catalina

filebeat.config.modules:

path: ${path.config}/modules.d/*.yml

reload.enabled: false

setup.template.settings:

index.number_of_shards: 1

setup.kibana:

output.redis:

hosts: ["172.31.2.105:6379"]

key: "k8s-magedu-app1"

db: 1

timeout: 5

password: "123456"