k8s 实战
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.10,v1.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 | +---------------+-------------------+-------+----------+-------------+
+---------------+-------------------+-------+----------+-------------+
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:定期检查kubedns和dnsmasq的健康状态
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:域名解析测试:
|
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-manager、kube-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⼀个特⾊功能,它在某些场景下应⽤,如节点NotReady、Node节点资源不⾜,把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:
kubernetes从1.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接⼝,放弃了v2的http接⼝,优势是⻓连接效率提升明显,缺点是使⽤不如以前⽅便,尤其对 不⽅便维护⻓连接的场景。 废弃了原来的⽬录结构,变成了纯粹的kv,⽤户可以通过前缀匹配模式模拟⽬录。 内存中不再保存value,同样的内存可以⽀持存储更多的key。 watch机制更稳定,基本上可以通过watch机制实现数据的完全同步。 提供了批量操作以及事务机制,⽤户可以通过批量事务请求来实现Etcd v2的CAS机制(批量事务⽀持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 | +---------------+-------------------+-------+----------+-------------+
+---------------+-------------------+-------+----------+-------------+
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
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作为⽹络插件。
|
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
|
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
|
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
|
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或者500m等CPU压缩值
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:
|
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/
|
四: 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 的初始化时间, 在此时间内的 pod,CPU 资源指标将不会被采纳,默认为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: #定义⽔平伸缩的⽬标对象, Deployment、ReplicationController/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:
|
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
#设置 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
|
4.7:从etcd删除pod:
适⽤于⾃动化场景
4.7.1:查看和namespace相关的数据:
4.7.2:从etcd查看具体某个对象的数据:
4.7.3:删除etcd指定资源:
五:持续集成与部署
5.1:jenkins环境准备:
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.2:gitlab环境准备:
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: PV及PVC实战案例:
默认情况下容器中的磁盘⽂件是⾮持久化的,对于运⾏在容器中的应⽤来说⾯临两个问题,第⼀:当容器挂掉 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版本开始⽀持PersistentVolume和PersistentVolumeClaim。 PV是对底层⽹络存储的抽象,即将⽹络存储定义为⼀种存储资源,将⼀个整体的存储资源拆分成多份后给不同的业务使 ⽤。 PVC是对PV资源的申请调⽤,就像POD消费node节点资源⼀样 ,pod是通过PVC将数据保存⾄PV,PV在保存⾄存储。 |
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:
验证redis的PV与PVC已经处于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" |