k8s
基础概念k8s架构api server 所有服务访问统一入口replication controller 维持副本期望数目scheduleretcd 键值对数据库 存储k8s集群所有重要信息(持久化)kublet 直接跟容器引擎进行交互,实现容器的管理kube-proxy 负责写入规则之iptables ipvs 实现服务映射访问其它组件
什么是pod控制器类型(控制器管理pod)
k8s网络通讯模式通讯规则通讯规则详解
构建k8s集群学习过程中使用vmware虚拟机vmware的配置配置说明
centos7虚拟机centos7安装centos7网络配置centos7环境配置docker安装k8s-master组件安装
生产环境
资源清单资源分类名称空间级别工作负载型资源(workload)服务发现及负载均衡型资源配置与存储型资源:特殊类型的存储卷
集群级资源元数据型资源
资源清单资源清单定义常见yaml字段查看字段查看日志 常用基本操作
pod的生命周期图解initCinitc 模版initC 解释
探针有三种类型的处理程序:livenessProbe 存活检测readinessProbe 就绪检测
start stop示例
pod控制器ReplicationController 和 ReplicaSet适用场景
Deployment功能deployment与rs关联示例创建扩容更新镜像回滚其它操作
DaemonSet适用场景示例
Job适用场景示例
CronJob适用场景并发策略示例
StatefulSetHorizontal Pod Autoscaling
服务发现Service 的概念Service 的类型ClusterIp说明图解示例
NodePort原理示例
LoadBalancerExternalName示例
VIP 和 Service 代理详情代理模式的分类
ingress功能官网实验1 http 代理实验二实验三 https
存储configMap解释ConfigMap 的创建1.用目录创建2.使用文件创建3.使用字面值创建4.yaml创建
Pod 中使用 ConfigMap1.用 ConfigMap 来替代环境变量2.用 ConfigMap 设置命令行参数3.使用volume将ConfigMap作为文件或目录直接挂载
ConfigMap 的热更新修改 configMapConfigMap 更新后滚动更新 Pod
SecretSecret有三种类型Service Account:Opaquekubernetes.io/dockerconfigjson
volumn目前支持的类型emptyDir应用场景示例
hostPath应用场景示例
集群调度调度器 Scheduler调度器亲和性节点亲和性软策略硬策略软硬合体操作符
Pod 亲和性
污点和容忍 Taint 和 Toleration污点污点的查看和清除容忍Tolerations
指定调度节点Pod.spec.nodeNamePod.spec.nodeSelector
集群安全机制认证鉴权访问控制 原理流程
HELM原理模版自定义部署常用的插件
kubeadm 修改证书有效期为100年
基础概念
k8s架构
api server 所有服务访问统一入口
replication controller 维持副本期望数目
scheduler
etcd 键值对数据库 存储k8s集群所有重要信息(持久化)
etcd是一个可信赖分布式键值存储服务,使用http版本
v2写入到内存v3 写入到db (k8s v1.11之前不支持)
kublet 直接跟容器引擎进行交互,实现容器的管理
kube-proxy 负责写入规则之iptables ipvs 实现服务映射访问
其它组件
coreDNS 可以为集群中的SVC创建一个域名IP的对应关系解析dashboard 给 K8S 集群提供一个 B/S 结构访问体系ingress controller 官方只能实现四层代理,INGRESS 可以实现七层代理federation 提供一个可以跨集群中心多K8S统一管理功能prometheus 提供K8S集群的监控能力elk 提供 K8S 集群日志统一分析介入平台
什么是pod
自主式pod 没有人管理的模式 一旦停止不会重启控制器管理的pod例如这是一个pod,只要这个pod启动 就会存在pause(用于AB容器共享网络栈和存储)aaa
控制器类型(控制器管理pod)
ReplicationController
用来确保容器应用的副本数始终保持在用户定义的副本数,
即如果有容器异常退出,会自动创建新的Pod 来替代;
而如果异常多出来的容器也会自动回收
ReplicaSet
ReplicaSet 跟ReplicationController 没有本质的不同,只是名字不一样,
并且ReplicaSet 支持集合式的selector虽然ReplicaSet 可以独立使用,
Deployment
但一般还是建议使用Deployment 来自动管理ReplicaSet ,
这样就无需担心跟其他机制的不兼容问题,
ReplicaSet 不支持rolling-update 但Deployment 支持
Deployment 为Pod 和ReplicaSet 提供了一个声明式定义(declarative) 方法,
用来替代以前的ReplicationController 来方便的管理应用。
典型的应用场景包括:
*定义Deployment 来创建Pod 和ReplicaSet*滚动升级和回滚应用
*扩容和缩容*暂停和继续Deployment返回
DaemonSet
Cron Job
管理基于时间的Job,即:
在给定时间点只运行一次周期性地在给定时间点运行返回
服务发现(service 来代理pod 当成微服务理解) 轮询算法
可以通过 Deployment 做代理 实现服务发现
k8s网络通讯模式
网络模型假定了所有Pod 都在一个可以直接连通的扁平的网络空间中
通讯规则
同一个Pod 内的多个容器之间:localhostPod 与Service 之间的通讯:各节点的Iptables 规则网络通讯模式各Pod 之间的通讯:Overlay Network 使用Flannel
概述 CoreOS 团队针对Kubernetes 设计的一个网络规划服务,简单来说,
它的功能是让集群中的不同节点主机创建的Docker 容器都具有全集群唯一的虚拟IP地址。
而且它还能在这些IP 地址之间建立一个覆盖网络(Overlay Network),
通过这个覆盖网络,将数据包原封不动地传递到目标容器内
图解
ETCD 和 Flannel 关系
存储管理 [Flannel 可分配的IP 地址段资源 ] Flannel在启动后向etcd插入分配的网段和机器对应关系监控ETCD 中每个 Pod 的实际地址,并在内存中建立维护 Pod 节点路由表
b
通讯规则详解
同一个Pod 内部通讯:同一个Pod 共享同一个网络命名空间,共享同一个Linux 协议栈
Pod1 至 Pod2
- Pod1 与Pod2 不在同一台主机,Pod的地址是与docker0在同一个网段的,
但docker0网段与宿主机网卡是两个完全不同的IP网段,并且不同Node之间的通信只能通过宿
主机的物理网卡进行。将Pod的IP和所在Node的IP关联起来,通过这个关联让Pod可以互相访问
- Pod1 与Pod2 在同一台机器,由Docker0 网桥直接转发请求至Pod2,不需要经过Flannel
Pod 至 Service的网络:目前基于性能考虑,全部为iptables 维护和转发
Pod 到外网:Pod 向外网发送请求,查找路由表, 转发数据包到宿主机的网卡, 宿主网卡完成路由选择后,iptables执行Masquerade,把源IP 更改为宿主网卡的IP, 然后向外网服务器发送请求
外网访问Pod:Service
构建k8s集群
学习过程中使用vmware虚拟机
vmware的配置
配置说明
1.自行寻找合适的vmware版本
2.配置nat网络模式的ip 子网掩码 网关
3.使用静态ip,不使用dhcp模式
centos7虚拟机
centos7安装
1. 可以到国内的镜像处下载 https://mirrors.163.com/centos/7.8.2003/isos/x86_64/
2. 安装过程。。。
3. 安装完成
centos7网络配置
1.使用nat网络模式
2.不想截图了 这里有篇一样的文章 https://blog.csdn.net/a785975139/article/details/53023590
centos7环境配置
1.安装基本的软件
yum
install -y conntrack ntpdate ntp ipvsadm ipset jq iptables
curl sysstat libseccomp
wget vim net-tools
git lrzsz
lrzsz xshell 传文件
从服务端发送文件到客户端:
sz filename
从客户端上传文件到服务端:
rz
2.关闭防火墙
systemctl stop firewalld
&& systemctl disable firewalld
3.设置防火墙为 Iptables 并设置空规则
yum -y
install iptables-services
&& systemctl start iptables
&& systemctl
enable iptables
&& iptables -F
&& service iptables save
4.设置主机名
hostnamectl set-hostname k8s-node01
hostnamectl set-hostname k8s-node02
hostnamectl set-hostname k8s-master01
5.加入ip到/etc/hosts
192.168.66.10 k8s-master01
192.168.66.20 k8s-node01
192.168.66.21 k8s-node02
6.关闭交换分区, /dev/mapper/centos-root
SELinux是干嘛的 参考 http://cn.linux.vbird.org/linux_basic/0440processcontrol_5.php
swapoff -a
&& sed -i
'/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
关闭SELinux
setenforce 0
&& sed -i
's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
7.调整内核参数,对于 K8S
cat > kubernetes.conf
<< EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
vm.overcommit_memory=1 # 不检查物理内存是否够用
vm.panic_on_oom=0 # 开启 OOM
fs.inotify.max_user_instances=8192
fs.inotify.max_user_watches=1048576
fs.file-max=52706963fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720
EOF
cp kubernetes.conf /etc/sysctl.d/kubernetes.conf
sysctl -p /etc/sysctl.d/kubernetes.conf
ps:执行这条可能会报错 sysctl: cannot
stat /proc/sys/net/netfilter/nf_conntrack_max: 没有那个文件或目录
解决办法: 先不管升级内核4之后自动调用 conntrack没有加载 这个可以省略 不过需要升级内核
执行 modprobe ip_conntrack 加载模块
查看 lsmod
|grep conntrack
8.调整系统时区
timedatectl set-timezone Asia/Shanghai
timedatectl set-local-rtc 0
systemctl restart rsyslog
&& systemctl restart crond
9.
关闭系统不需要服务 邮件服务
systemctl stop postfix
&& systemctl disable postfix
10.设置 rsyslogd 和 systemd journald 日志
mkdir /var/log/journal
mkdir /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/99-prophet.conf
<<EOF
[Journal]
# 持久化保存到磁盘
Storage=persistent
# 压缩历史日志
Compress=yesSyncIntervalSec=5m
RateLimitInterval=30s
RateLimitBurst=1000
# 最大占用空间 10G
SystemMaxUse=10G
# 单日志文件最大 200M
SystemMaxFileSize=200M
# 日志保存时间 2 周
MaxRetentionSec=2week
# 不将日志转发到 syslog
ForwardToSyslog=no
EOF
systemctl restart systemd-journald
11.升级内核为4.4
(好像不升级也行吧
)
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
yum --enablerepo
=elrepo-kernel
install -y kernel-lt
grub2-set-default
'CentOS Linux (4.4.189-1.el7.elrepo.x86_64) 7 (Core)'
docker安装
1.kube-proxy开启ipvs的前置条件
modprobe br_netfilter
cat > /etc/sysconfig/modules/ipvs.modules
<<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules
&& bash /etc/sysconfig/modules/ipvs.modules
&&lsmod
| grep -e ip_vs -e nf_conntrack_ipv4
2.安装docker 使用阿里云的centos7
安装 Docker 软件
yum
install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum update -y
&& yum -y
install docker-ce
reboot
systemctl start docker
&& systemctl
enable docker
mkdir /etc/docker
cat > /etc/docker/daemon.json
<<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {"max-size": "100m" }
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
systemctl daemon-reload
&& systemctl restart docker
&& systemctl
enable docker
k8s-master组件安装
1.安装 Kubeadm (主从配置)
cat <<EOF
> /etc/yum.repos.d/kubernetes.repo
[kubernetes
]
name
=Kubernetes
baseurl
=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled
=1
gpgcheck
=0
repo_gpgcheck
=0
gpgkey
=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum -y
install kubeadm-1.15.1 kubectl-1.15.1 kubelet-1.15.1
systemctl
enable kubelet.service
2. 初始化主节点
2.1 生成配置文件
kubeadm config print init-defaults
> kubeadm-config.yaml
2.2 修改配置文件
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress:192.168.66.10
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: k8s-master01
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager:
{}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: v1.15.1
networking:
dnsDomain: cluster.local
podSubnet:
"10.244.0.0/16"
serviceSubnet: 10.96.0.0/12
scheduler:
{}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
featureGates:
SupportIPVSProxyMode:
true
mode: ipvs
2.3 初始化主节点
(虚拟机需要分配两个cpu
)
需要下载需要的镜像
需要科.学.上.网 kubeadm init --config
=kubeadm-config.yaml --experimental-upload-certs
| tee kubeadm-init.log
使用阿里云的仓库 kubeadm init --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.15.1 --apiserver-advertise-address 192.168.66.10 --pod-network-cidr
=10.244.0.0/16
| tee kubeadm-init.log
3.加入主节点以及其余工作节点
查看安装日志
(2.3的kubeadm-init.log
)中的加入命令即可
删除节点 master中执行 kubectl delete node k8s-node01
节点加入集群 kubeadm reset
&& kubeadm
join ...
master生成的加入token为24h 过期后
kubeadm token generate
kubeadm token create
<token
> --print-join-command --ttl
=0
4.部署网络 flannel网络插件
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
5.查看系统的容器
kubectl get pod -n kube-system
6. 如果是遇到节点的flannel报错Error from server: Get https://192.168.66.21:10250/containerLogs/kube-system/kube-flannel-ds-jj7fz/kube-flannel: dial tcp 192.168.66.21:10250: connect: no route to host
解决方法:将该节点踢出,删除节点上的容器镜像,然后重新把这个节点加入到集群,就是有效
生产环境
资源清单
资源分类
名称空间级别
工作负载型资源(workload)
Pod、ReplicaSet、Deployment、StatefulSet、DaemonSet、Job、CronJob
(ReplicationController在v1.11版本被废弃
)
服务发现及负载均衡型资源
(ServiceDiscoveryLoadBalance
):Service、Ingress、
...
配置与存储型资源:
Volume(存储卷)、
CSI(容器存储接口,可以扩展各种各样的第三方存储卷)
特殊类型的存储卷
ConfigMap(当配置中心来使用的资源类型)、Secret(保存敏感数据)、DownwardAPI(把外部环境中的信息输出给容器)
集群级资源
Namespace、Node、Role、ClusterRole、RoleBinding、ClusterRoleBinding
元数据型资源
HPA、PodTemplate、LimitRange
资源清单
资源清单定义
在k8s中,一般使用yaml格式的文件来创建符合我们预期期望的pod,这样的yaml文件我们一般称为资源清单
常见yaml字段
参数名字段类型说明
versionstring这里指k8s的api版本 默认为v1 可以通过 kubectl api-versions查看
查看字段
kubectl explain pod 可以去文档找kubectl explain pod.xxxxx
查看日志 常用基本操作
kubectl get node --show-labelskubectl get pod --show-labels [-w] [-o wide]kubectl describe pod xxx-podkubectl logs xxx-pod -c 容器名称删除 pod kubectl delete pod xxx-pod删除 pod kubectl delete pod --all进入pod中的容器 kubectl exec xxx-pod [-c xxx容器] -it -- /bin/sh查看pod标签 kubectl get pod --show-labels修改标签 kubectl label pod xxx-pod label=newlabel --overwrite=True查看适用版本 kubectl explain rs/deployment/pod/job打标签 kubectl label pod you-pod app=hello --overwrite=true
pod的生命周期
图解
initC
initc 模版
apiVersion: v1
kind: Pod
metadata:
name: myapp
-pod
labels:
app: myapp
spec:
containers:
name: myapp
-container
image: busybox
command: ['sh','-c','echo The app is running! && sleep 3600']
initContainers:
- name: init
-myservice
image: busybox
command: ['sh','-c','until nslookup myservice; do echo waiting for myservice; sleep 2;done;']
- name: init
-mydb
image: busybox
command: ['sh','-c','until nslookup mydb; do echo waiting for mydb; sleep 2;done;']
kind: Service
apiVersion: v1
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
kind: Service
apiVersion: v1
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
initC 解释
每个pod可以有多个initC
Init容器与普通的容器非常像,除了如下两点:
Init容器总是运行到成功完成为止
每个Init容器都必须在下一个Init容器启动之前成功完成
如果Pod的Init容器失败,Kubernetes会不断地重启该Pod,直到Init容器成功为止。
然而,如果Pod对应的restartPolicy为Never,它不会重新启动
Init容器会按顺序在网络和数据卷
(pause容器
)初始化之后启动
探针
探针是由kubelet对容器执行的定期诊断
有三种类型的处理程序:
ExecAction:在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功。TCPSocketAction:对指定端口上的容器的IP地址进行TCP检查。如果端口打开,则诊断被认为是成功的。HTTPGetAction:对指定的端口和路径上的容器的IP地址执行HTTPGet请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的
livenessProbe 存活检测
exec 方式
apiVersion: v1
kind: Pod
metadata:
name: liveness
-exec
-pod
namespace: default
spec:
containers:
- name: liveness
-exec
-container
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep3600"]
livenessProbe:
exec:
command: ["test","-e","/tmp/live"]
initialDelaySeconds: 1
periodSeconds: 3
http get 方式
apiVersion: v1
kind: Pod
metadata:
name: liveness
-httpget
-pod
namespace: default
spec:
containers:
- name: liveness
-httpget
-container
image: liuqt
:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
livenessProbe:
httpGet:
port: http
path: /hostname
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 10
tcp
apiVersion: v1
kind: Pod
metadata:
name: probe
-tcp
spec:
containers:
- name: nginx
image: liuqt
:v1
livenessProbe:
initialDelaySeconds: 5
timeoutSeconds: 1
tcpSocket:
port: 80
readinessProbe 就绪检测
http get 方式
apiVersion: v1
kind: Pod
metadata:
name: readiness
-httpget
-pod
namespace: default
spec:
containers:
- name: readiness
-httpget
-container
image: liuqt
:v1
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 80
path: /hostname
initialDelaySeconds: 1
periodSeconds: 3
start stop
示例
apiVersion: v1
kind: Pod
metadata:
name: lifecycle
-demo
spec:
containers:
- name: lifecycle
-demo
-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler >/usr/share/message"]
preStop:
exec:
command: ["/bin/sh", "-c", "echo Hello from the poststop handler >/usr/share/message"]
pod控制器
ReplicationController 和 ReplicaSet
适用场景
rs支持支持集合式的 selector 即标签功能,rc已被rs替代确保pod指定的副本数示例
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: liuqt
image: liuqt
:v1
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
Deployment
功能
支持回滚更新、扩容、更新镜像会创建对应的rs来管理pod
deployment与rs关联
图
示例
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: liuqt
image: liuqt
:v1
ports:
- containerPort: 80
创建
kubectl create -f 上面的deployment.yaml --record
扩容
kubectl scale deployment nginx-deployment --replicas 10
更新镜像
kubectl
set image deployment/nginx-deployment liuqt
=liuqt:v2
回滚
kubectl rollout undo deployment/nginx-deployment
kubectl rollout status deployment/nginx-deployment
kubectl get rs
其它操作
kubectl
set image deployment/nginx-deployment nginx
=nginx:1.91
kubectl rollout status deployments nginx-deployment
kubectl rollout undo deployment/nginx-deployment
kubectl rollout
history deployment/nginx-deployment
kubectl rollout undo deployment/nginx-deployment --to-revision
=2
kubectl rollout pause deployment/nginx-deployment
DaemonSet
适用场景
每个node仅运行一个副本,如日志收集,监控等
示例
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: deamonset
-example
labels:
app: daemonset
spec:
selector:
matchLabels:
name: deamonset
-example
template:
metadata:
labels:
name: deamonset
-example
spec:
containers:
- name: daemonset
-example
image: liuqt
:v1
Job
适用场景
单次任务:计算任务
示例
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
metadata:
name: pi
spec:
containers:
- name: pi
image: perl
command: ["perl","-Mbignum=bpi","-wle","print bpi(2000)"]
restartPolicy: Never
CronJob
适用场景
定时任务:备份数据库、发邮件定时去创建job
并发策略
Allow(默认):允许并发运行 JobForbid:禁止并发运行,如果前一个还没有完成,则直接跳过下一个Replace:取消当前正在运行的 Job,用一个新的来替换
示例
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
StatefulSet
有状态服务 mysql mongo等
Horizontal Pod Autoscaling
控制控制器实现自动扩容
服务发现
Service 的概念
类似于微服务
Service 的类型
ClusterIp
默认类型,自动分配一个仅 Cluster 内部可以访问的虚拟 IP
说明
clusterIP 主要在每个 node 节点使用 iptables,将发向 clusterIP 对应端口的数据,转发到 kube-proxy 中。
然后 kube-proxy 自己内部实现有负载均衡的方法,并可以查询到这个
service 下对应 pod 的地址和端口,进而把数据转发给对应的 pod 的地址和端口
图解
图例说明
为了实现图上的功能,主要需要以下几个组件的协同工作
1.apiserver 用户通过kubectl命令向apiserver发送创建service的命令,apiserver接收到请求后将数据存储到etcd中
2.kube-proxy kubernetes的每个节点中都有一个叫做kube-porxy的进程,这个进程负责感知service,pod的变化,并将变化的信息写入本地的iptables规则中
3.iptables 使用NAT等技术将virtualIP的流量转至endpoint中
示例
deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
-deploy
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: myapp
release: stabel
template:
metadata:
labels:
app: myapp
release: stabel
env: test
spec:
containers:
- name: myapp
image: liuqt
:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
svc
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
type: ClusterIP
selector:
app: myapp
release: stabel
ports:
- name: http
port: 80
targetPort: 80
NodePort
在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过: NodePort 来访问该服务可以使用nginx负载均衡每台node
原理
nodePort 的原理在于在 node 上开了一个端口,将向该端口的流量导入到 kube-proxy,然后由 kube-proxy 进一步到给对应的 pod
示例
deployment 使用上面的clasterIPsvc
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
type: NodePort
selector:
app: myapp
release: stabel
ports:
- name: http
port: 80
targetPort: 80
LoadBalancer
需要搭建在云服务器,需要云供应商 ,没啥用。。。在 NodePort 的基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到: NodePort
ExternalName
把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有 kubernetes 1.7 或更高版本的 kube-dns 才支持例如:node中需要访问外部的mysql等 ,定义一个mysql-svc供pod访问即可
示例
kind: Service
apiVersion: v1
metadata:
name: mysql
-service
namespace: default
spec:
type: ExternalName
externalName: 127.0.0.1(你的mysql地址)
VIP 和 Service 代理
详情
在 Kubernetes 集群中,每个 Node 运行一个kube-proxy进程。
kube-proxy负责为Service实现了一种VIP(虚拟 IP)的形式,而不是ExternalName的形式。
在 Kubernetes v1.0 版本,代理完全在 userspace。
在Kubernetes v1.1 版本,新增了 iptables 代理,但并不是默认的运行模式。
从 Kubernetes v1.2 起,默认就是iptables 代理。
在 Kubernetes v1.8.0-beta.0 中,添加了 ipvs 代理在 Kubernetes 1.14 版本开始默认使用ipvs 代理
在 Kubernetes v1.0 版本,Service是 “4层”(TCP/UDP over IP)概念。
在 Kubernetes v1.1 版本,新增了Ingress API(beta 版),用来表示 “7层”(HTTP)服务
代理模式的分类
userspace 代理模式iptables 代理模式ipvs 代理模式
rr:轮询调度lc:最小连接数dh:目标哈希sh:源哈希sed:最短期望延迟nq:不排队调度
ingress
功能
使用ingress可以实现将内部服务实现七层代理
官网
ingress这里用了nodeport模式 kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.40.2/deploy/static/provider/baremetal/deploy.yaml上面的yaml有个坑
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1betal
其他说明
只需要apply deploy.yaml 一个yaml就能开启ingress代理
deploy.yaml 里面需要的镜像 可能无法正常下载
可以通过阿里云容器镜像服务 代下
然后自行修改标签即可
实验1 http 代理
deployment && service
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
-deplyment1
spec:
replicas: 3
template:
metadata:
labels:
name: nginx1
spec:
containers:
- name: nginx
image: liuqt
:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
-svc1
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx1
ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx
-test
spec:
rules:
- host: www1.liuqt.com
http:
paths:
- path: /
backend:
serviceName: nginx
-svc1
servicePort: 80
访问 通过 kubectl get svc -n ingress-nginx 可以查看到向外暴露的端口在自己的主机hosts添加规则 www.xxx.com:11111 即可访问到上面的服务
实验二
需求示例deployment && service
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: deplyment1
spec:
replicas: 3
template:
metadata:
labels:
name: nginx1
spec:
containers:
- name: nginx1
image: liuqt
:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: svc1
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx1
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: deplyment2
spec:
replicas: 3
template:
metadata:
labels:
name: nginx2
spec:
containers:
- name: nginx2
image: liuqt
:v2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: svc2
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx2
ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx
-test
spec:
rules:
- host: www1.liuqt.com
http:
paths:
- path: /
backend:
serviceName: svc1
servicePort: 80
- host: www2.liuqt.com
http:
paths:
- path: /
backend:
serviceName: svc2
servicePort: 80
访问方式同实验一
实验三 https
参考 示例创建证书
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj
"/CN=nginxsvc/O=nginxsvc"
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
deploymentingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx
-test
spec:
tls:
- hosts:
- www2.liuqt.com
secretName: tls
-secret
rules:
- host: www2.liuqt.com
http:
paths:
- path: /
backend:
serviceName: nginx
-svc
servicePort: 80
存储
configMap
解释
许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。
ConfigMap API 给我们提供了向容器中注入配置信息的机制,
ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者 JSON 二进制大对象
ConfigMap 的创建
1.用目录创建
mkdir config
echo a
>config/a
echo b
>config/b
kubectl create configmap special-config --from-file
=config/
kubectl get configmap special-config -o go-template
='{{.data}}'
2.使用文件创建
echo -e
"a=b\nc=d" | tee config.env
kubectl create configmap special-config --from-file
=config.env
kubectl create configmap special-config --from-env-file
=config.env
kubectl get configmap special-config -o go-template
='{{.data}}'
kubectl get configmap special-config -o yaml
3.使用字面值创建
kubectl create configmap special-config --from-literal
=special_how
=very --from-literal
=special_type
=charm
kubectlget configmaps special-config -o yaml
4.yaml创建
apiVersion: v1
kind: ConfigMap
metadata:
name: special
-config
namespace: default
data:
special.how: very
special.type: charm
Pod 中使用 ConfigMap
1.用 ConfigMap 来替代环境变量
示例
apiVersion: v1
kind: Pod
metadata:
name: test
-pod
spec:
containers:
- name: test
-container
image: busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special
-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special
-config
key: special.type
envFrom:
- configMapRef:
name: env
-config
restartPolicy: Never
2.用 ConfigMap 设置命令行参数
示例
apiVersion: v1
kind: Pod
metadata:
name: dapi
-test
-pod
spec:
containers:
- name: test
-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special
-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special
-config
key: special.type
restartPolicy: Never
3.使用volume将ConfigMap作为文件或目录直接挂载
示例
apiVersion: v1
kind: Pod
metadata:
name: vol
-test
-pod
spec:
containers:
- name: test
-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "cat /etc/config/special.how" ]
volumeMounts:
- name: config
-volume
mountPath: /etc/config
volumes:
- name: config
-volume
configMap:
name: special
-config
restartPolicy: Never
ConfigMap 的热更新
修改 configMap
kubectl edit configmap log-config修改key值后等待大概 10 秒钟时间,再次查看环境变量的值
ConfigMap 更新后滚动更新 Pod
更新 ConfigMap 目前并不会触发相关 Pod 的滚动更新,可以通过修改 pod annotations 的方式强制触发滚动更新
kubectl patch deployment my-nginx --patch
'{"spec": {"template": {"metadata": {"annotations":{"version/config": "20190411" }}}}}'
啦啦啦
更新 ConfigMap 后:
使用该 ConfigMap 挂载的 Env 不会同步更新
使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新
Secret
解决了密码、token、密钥等敏感数据的配置问题
Secret有三种类型
Service Account:
用来访问Kubernetes API,由Kubernetes自动创建,并且会自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount目录中查看 kubectl exec xxx-pod-xxx ls /run/secrets/kubernetes.io/serviceaccount
Opaque
base64编码格式的Secret,用来存储密码、密钥等;示例
echo -n
"admin" | base64
YWRtaW4
=
echo -n
"1f2d1e2e67df" | base64
MWYyZDFlMmU2N2Rm
yaml 示例
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: MWYyZDFlMmU2N2Rm
username: YWRtaW4=
创建secret kubectl create -f secrets.yml使用方式一:Volume方式
apiVersion: v1
kind: Pod
metadata:
labels:
name: db
name: db
spec:
volumes:
- name: secrets
secret:
secretName: mysecret
containers:
- image: nginx
:v1
name: db
volumeMounts:
- name: secrets
mountPath: "/etc/secrets"
readOnly: true
ports:
- name: cp
containerPort: 80
hostPort: 80
使用方式二: 将Secret导出到环境变量中
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: wordpress
-deployment
spec:
replicas: 2
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: wordpress
visualize: "true"
spec:
containers:
- name: "wordpress"
image: "wordpress"
ports:
- containerPort: 80
env:
- name: WORDPRESS_DB_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
kubernetes.io/dockerconfigjson
用来存储私有docker registry的认证信息(需要认证的镜像自动登陆)示例
kubectl create secret docker-registry myregistrykey \
--docker-server
=DOCKER_REGISTRY_SERVER --docker-username
=DOCKER_USER \
--docker-password
=DOCKER_PASSWORD --docker-email
=DOCKER_EMAIL
创建pod时候使用
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: foo
image: app
:v1
imagePullSecrets:
- name: myregistrykey
volumn
参考中文k8s文档参考
目前支持的类型
emptyDir、hostPath、
gcePersistentDisk、awsElasticBlockStore、nfs、iscsi
glusterfs、rbd、gitRepo、secret
persistentVolumeClaim
emptyDir
应用场景
emptyDir 磁盘的作用:
普通空间,基于磁盘的数据存储
作为从崩溃中恢复的备份点
存储那些那些需要长久保存的数据,例web服务中的数据
示例
apiVersion: v1
kind: Pod
metadata:
name: test
-pd
spec:
containers:
- image: liuqt
:v1
name: test
-container
volumeMounts:
- mountPath: /cache
name: cache
-volume
volumes:
- name: cache
-volume
emptyDir: {}
hostPath
应用场景
一个hostPath类型的磁盘就是挂在了主机的一个文件或者目录,这个功能可能不是那么常用,但是这个功能提供了一个很强大的突破口对于某些应用来说
例如,如下情况我们旧可能需要用到hostPath
某些应用需要用到docker的内部文件,这个时候只需要挂在本机的/var/lib/docker作为hostPath
在容器中运行cAdvisor,这个时候挂在/dev/cgroups
示例
apiVersion: v1
kind: Pod
metadata:
name: test
-pd
spec:
containers:
- image: k8s.gcr.io/test
-webserver
name: test
-container
volumeMounts:
- mountPath: /test
-pd
name: test
-volume
volumes:
- name: test
-volume
hostPath
:
path: /data
type: Directory
集群调度
调度器 Scheduler
主要的任务是把定义的 pod 分配到集群的节点上
调度器亲和性
节点亲和性
解释
节点亲和性
(pod 和node亲和性
)
软策略
分班了 我想去张三老师的班级
硬策略
我必须去张三老师的班级
Pod 亲和性
软策略
分班了 我同桌关系很好 能和他去一个班级最好
硬策略
分班了 我同桌关系很好 一定和他去
pod.spec.nodeAffinity
软策略
preferredDuringSchedulingIgnoredDuringExecution示例
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node
-affinity
-pod
spec:
containers:
- name: with
-node
-affinity
image: liuqt
:v1 affinity
:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- k8s
-node100
硬策略
requiredDuringSchedulingIgnoredDuringExecution示例
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node
-affinity
-pod
spec:
containers:
- name: with
-node
-affinity
image: liuqt
:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- k8s
-node02
软硬合体
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node
-affinity
-pod
spec:
containers:
- name: with
-node
-affinity
image: liuqt
:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- k8s
-node02
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s
-node01
操作符
In:label 的值在某个列表中 NotIn:label 的值不在某个列表中 Gt:label 的值大于某个值 Lt:label 的值小于某个值 Exists:某个 label 存在 DoesNotExist:某个 label 不存在
Pod 亲和性
示例
apiVersion: v1
kind: Pod
metadata:
name: pod
-3
labels:
app: pod
-3
spec:
containers:
- name: pod
-3
image: hub.atguigu.com/library/myapp
:v1
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- pod1
topologyKey: kubernetes.io/hostname
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- pod2
topologyKey: kubernetes.io/hostname
说明
调度策略匹配标签操作符拓扑域支持调度目标
nodeAffinity主机In, NotIn, Exists,DoesNotExist, Gt, Lt否指定主机podAffinitypodIn, NotIn, Exists,DoesNotExist是POD与指定POD同一拓扑域podAnitAffinitypodIn, NotIn, Exists,DoesNotExist是POD与指定POD同一拓扑域
污点和容忍 Taint 和 Toleration
hh 打呼噜
污点
设置节点的污点 kubectl taint nodes k8s-node01 key=value:effect每个污点有一个 key 和 value 作为污点的标签,其中 value 可以为空,effect 描述污点的作用effect 支持如下三个选项
NoSchedule:表示 k8s 将不会将 Pod 调度到具有该污点的 Node 上 PreferNoSchedule:表示 k8s 将尽量避免将 Pod 调度到具有该污点的 Node 上 NoExecute:表示 k8s 将不会将 Pod 调度到具有该污点的 Node 上,同时会将 Node 上已经存在的 Pod 驱逐出去
污点的查看和清除
kubectl taint nodes node1 key1
=value1:NoSchedule
kubectl describe pod pod-name
kubectl taint nodes node1 key1:NoSchedule-
容忍Tolerations
设置在 pod.spec.tolerations示例
apiVersion: v1
kind: Pod
metadata:
name: pod
-3
labels:
app: pod
-3
spec:
containers:
- name: pod
-3
image: hub.atguigu.com/library/myapp
:v1
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
tolerationSeconds: 3600
不指定污点时,容忍所有的污点key
tolerations:
- operator: "Exists"
不指定 effect 值时,表示容忍所有的污点作用
tolerations:
- key: "key"
operator: "Exists"
有多个 Master 存在时,防止资源浪费,可以如下设置
kubectl taint nodes k8s-master01 node-role.kubernetes.io/master=:PreferNoSchedule
指定调度节点
Pod.spec.nodeName
示例
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myweb
spec:
replicas: 7
template:
metadata:
labels:
app: myweb
spec:
nodeName: k8s
-node01
containers:
- name: myweb
image: app
:v1
ports:
- containerPort: 80
Pod.spec.nodeSelector
示例
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myweb
spec:
replicas: 2
template:
metadata:
labels:
app: myweb
spec:
nodeSelector:
disk: ssd
containers:
- name: myweb
image: app
:v1
ports:
- containerPort: 80
打标签 kubectl label node node01 disk=ssd修改deployment副本数 kubectl edit deploayment xxx-deployment
集群安全机制
认证
鉴权
访问控制 原理流程
HELM
原理
模版自定义
部署常用的插件
kubeadm 修改证书有效期为100年