k8s kubesphere devops
一、k8s 集群部署
1、k8s 快速入门
1)、简介
Kubernetes 简称 k8s。是用于自动部署,扩展和管理容器化应用程序的开源系统。
中文官网:https://kubernetes.io/zh/
中文社区:https://www.kubernetes.org.cn/
官方文档:https://kubernetes.io/zh/docs/home/
社区文档:http://docs.kubernetes.org.cn/
- 部署模式的演变
https://kubernetes.io/zh/docs/concepts/overview/
2)、架构
1、整体主从方式
以服务器为主节点,其他服务器为主节点node节点
2、Master 节点架构
-
- 对外暴露 K8S 的 api 接口是外部资源操作的唯一入口
- 提供认证、授权、访问控制API 注册和发现等机制
-
- etcd 它是一个具有一致性和高可用性的键值数据库,可用作保存 Kubernetes 所有集群数据的背景数据库。
- Kubernetes 集群的 etcd 数据库通常需要备份计划
-
- 主节点上的组件监控新创建的未指定操作节点 Pod,并选择节点 让 Pod 在上面操作。
- 所有对 k8s 集群操作必须通过主节点进行调度
-
- 控制器组件在主节点上运行
- 这些控制器包括:
- 节点控制器(Node Controller): 在节点出现故障时,负责通知和响应。
- 副本控制器(Replication Controller): 负责维护系统中每个副本控制器对象的正确数量 Pod。
- 端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入) Service 与 Pod) 。
- 服务帐户和令牌控制器(Service Account & Token Controllers): 为新的命名 创建默认账户和空间 API 访问令牌
3、Node 节点架构
-
- 在集群中的每个节点上运行的代理。它确保容器在运行中 Pod 中。
- 负责维护容器的生命周期和生命周期 Volume(CSI)和网络(CNI)的管理;
-
- 负责为 Service 提供 cluster 内部服务发现与负载平衡;
-
容器运行环境(Container Runtime)
- 容器运行环境是负责容器运行的软件。
- Kubernetes 支持多个容器运行环境: Docker、 containerd、cri-o、 rktlet 以及任何实现 Kubernetes CRI (容器运行环境接口)。
-
- 这是一个保护过程,有助于提供集群层面的日志
3)、概念
-
Container:容器,可以 docker 启动容器
-
Pod:
- k8s 使用 Pod 组织一组容器
- 一个 Pod 所有容器共享同一网络。
- Pod 是 k8s 最小部署单元
-
Volume
- 声明在 Pod 可访问的文件目录在容器中
- 可挂载 Pod 在一个或多个容器指定的路径下
- 支持抽象(本地存储、分布式存储、云存储…)
-
Controllers:部署和管理更高层次的对象 Pod;
- ReplicaSet:确保预期的 Pod 副本数量
- Deplotment:无状态应用部署
- StatefulSet:有状态应用部署
- DaemonSet:确保所有 Node 所有一个指定 Pod
- Job:一次性任务
- Cronjob:定时任务
-
Deployment:
- 定义一组 Pod 副本数量、版本等
- 通过控制器(Controller)维持 Pod 数量(自动返回 复失败的 Pod)
- 指定的策略控制版本(滚动升级、回滚等。)通过控制器
- Service
- 定义一组 Pod 的访问策略
- Pod 提供一个或多个负载平衡 Pod 的稳定 访问地址
- 支持多种方式(ClusterIP、NodePort、LoadBalance)
- Namespace:命名空间,逻辑隔离
- 集群内的逻辑隔离机制(鉴权、资源)
- 每个资源都属于一个 namespace
- 同一个 namespace 所有资源名称不能重复
- 不同 namespace 可重复资源名称
API:
我们通过 kubernetes 的 API 操作整个集群
可以通过 kubectl、ui、curl 最终发送 http json/yaml 方式请求 API Server,然后控制 k8s 集群。
4)快速体验
1、安装 minikube
https://github.com/kubernetes/minikube/releases
下载 minikube-windows-amd64.exe
改名为 minikube.exe
打开 VirtualBox
,打开cmd运行
minikube start --vm-driver=virtualbox --registry-mirror=https://registry.docker-cn.com
等待 20 大约几分钟
2、体验 nginx 部署升级
提交一个ngix deployment
kubectl apply -f https://k8s.io/examples/application/deployment.yaml
升级nginx deployment
kubectl apply -f https://k8s.io/examples/application/deployment-update.yaml
扩容nginx deployment
kubectl apply -f https://k8s.io/examples/application/deployment-scale.yaml
5)、流程叙述
1、通过 Kubectl 提交一个创建RC(Replication Controller)的请求,该请求通过 APIServer被写入etcd 中
2、此时Controller Manager 通过API Server 的监听资源变化的接口监听到此RC 事件
3、分析之后,发现当前集群中还没有它所对应的Pod 实例,
4、于是根据RC 里的Pod 模板定义生成一个Pod 对象,通过APIServer 写入etcd
5、此事件被Scheduler 发现,它立即执行一个复杂的调度流程,为这个新 Pod 选定一 个落户的Node,然后通过 API Server 讲这一结果写入到 etcd 中,
6、目标 Node 上运行的 Kubelet 进程通过 APIServer 监测到这个“新生的”Pod,并按照它 的定义,启动该 Pod 并任劳任怨地负责它的下半生,直到Pod 的生命结束。
7、随后,我们通过Kubectl 提交一个新的映射到该 Pod 的Service 的创建请求
8、ControllerManager 通过Label 标签查询到关联的Pod 实例,然后生成Service 的 Endpoints 信息,并通过APIServer 写入到 etcd 中
9、接下来,所有 Node 上运行的 Proxy 进程通过 APIServer 查询并监听 Service 对象与 其对应的 Endpoints 信息,建立一个软件方式的负载均衡器来实现 Service 访问到后端 Pod 的流量转发功能。
2、k8s 集群安装
1、kubeadm
kubeadm 是官方社区推出的一个用于快速部署 kubernetes 集群的工具。 这个工具能通过两条指令完成一个 kubernetes 集群的部署:
# 创建一个 Master 节点
$ kubeadm init
# 将一个 Node 节点加入到当前集群中
$ kubeadm join <Master 节点的 IP 和端口 >
2、前置要求
一台或多台机器,操作系统 CentOS7.x-86_x64
硬件配置:2GB 或更多 RAM,2 个 CPU 或更多 CPU,硬盘 30GB 或更多
集群中所有机器之间网络互通
可以访问外网,需要拉取镜像
禁止 swap 分区
3、部署步骤
1.在所有节点上安装 Docker 和 kubeadm
2.部署 Kubernetes Master
3.部署容器网络插件
4.部署 Kubernetes Node,将节点加入 Kubernetes 集群中
5.部署 Dashboard Web 页面,可视化查看 Kubernetes 资源
4、环境准备
1、准备工作
- 我们可以使用 vagrant 快速创建三个虚拟机。虚拟机启动前先设置 virtualbox 的主机网络。现全部统一为 192.168.56.1,以后所有虚拟机都是 56.x 的 ip 地址
- 设置虚拟机存储目录,防止硬盘空间不足
2、启动三个虚拟机
Vagrantfile:
Vagrant.configure("2") do |config|
(1..3).each do |i|
config.vm.define "k8s-node#{i}" do |node|
# 设置虚拟机的Box
node.vm.box = "centos/7"
# 设置虚拟机的主机名
node.vm.hostname="k8s-node#{i}"
# 设置虚拟机的IP
node.vm.network "private_network", ip: "192.168.56.#{99+i}", netmask: "255.255.255.0"
# 设置主机与虚拟机的共享目录
# node.vm.synced_folder "~/Documents/vagrant/share", "/home/vagrant/share"
# VirtaulBox相关配置
node.vm.provider "virtualbox" do |v|
# 设置虚拟机的名称
v.name = "k8s-node#{i}"
# 设置虚拟机的内存大小
v.memory = 4096
# 设置虚拟机的CPU个数
v.cpus = 4
end
end
end
end
-
使用我们提供的 vagrant 文件,复制到非中文无空格目录下,运行
vagrant up
启动三个虚拟机。其实 vagrant 完全可以一键部署全部 k8s 集群。 https://github.com/rootsongjc/kubernetes-vagrant-centos-cluster http://github.com/davidkbainbridge/k8s-playground -
进入三个虚拟机,开启 root 的密码访问权限。
进去系统,如第一台k8s-node1
vagrant ssh k8s-node1
su root #密码为 vagrant
vi /etc/ssh/sshd_config
修改
PasswordAuthentication yes
重启服务
systemctl restart sshd.service
所有虚拟机设置为 4 核 4G
关闭所有机器,全局设定设置net网络
每个机器设置网络连接方式为nat,界面名称为上述创建的NatNetwork,地址一定要随机在生成一个
3、设置 linux 环境(三个节点都执行)
关闭防火墙:
systemctl stop firewalld
systemctl disable firewalld
关闭selinux:
sed -i 's/enforcing/disabled/' /etc/selinux/config
set enforce 0
关闭 swap:
#关闭sawp分区 (可以不关闭,使用参数--ignore-preflight-errors=swap)
#临时关闭
swapoff -a
#永久
sed -ri 's/.*swap.*/#&/' /etc/fstab
#验证,swap 必须为 0;
free -g
添加主机名与IP 对应关系
cat > /etc/hosts << EOF 10.0.2.15 k8s-node1 10.0.2.4 k8s-node2 10.0..5 k8s-node3 EOF
#指定新的hostname
hostnamectl set-hostname <newhostname>
su 切换过来
将桥接的 IPv4 流量传递到 iptables 的链:
cat > /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF
sysctl --system
疑难问题:
遇见提示是只读的文件系统,运行如下命令
mount -o remount rw /
date 查看时间 (可选)
yum install -y ntpdate
同步最新时间
ntpdate time.windows.com
时间同步
echo '*/5 * * * * /usr/sbin/ntpdate -u ntp.api.bz' >>/var/spool/cron/root
systemctl restart crond.service
crontab -l
5、所有节点安装Docker、kubeadm、kubelet、kubectl
Kubernetes 默认 CRI(容器运行时)为 Docker,因此先安装 Docker。
1、安装 docker
1、卸载系统之前的 docker
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
2、安装 Docker-CE
源添加
#源添加
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -P /etc/yum.repos.d/ http://mirrors.aliyun.com/repo/epel-7.repo
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
yum clean all
yum install -y bash-completion.noarch
安装必须的依赖,系统工具
sudo yum install -y yum-utils
设置 docker repo 的 yum 位置
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
可以查看版本安装
yum list docker-ce --showduplicates | sort -r
安装 docker,以及 docker-cli,可以指定一下版本
sudo yum install -y docker-ce-18.09.9-3.el7 docker-ce-cli-18.09.9-3.el7 containerd.io
3、配置 docker 加速
sudo mkdir -p /etc/docker
sudo echo -e "{
\n \"registry-mirrors\": [\"https://5955cm2y.mirror.aliyuncs.com\"],\"exec-opts\": [\"native.cgroupdriver=systemd\"]\n}" > /etc/docker/daemon.json
sudo systemctl daemon-reload
sudo systemctl restart docker
4、启动 docker & 设置 docker 开机自启
systemctl enable docker
基础环境准备好,可以给三个虚拟机备份一下;为 node3 分配 16g,剩下的 3g。方便未来测试
2、添加阿里云 yum 源
cat > /etc/yum.repos.d/kubernetes.repo << EOF [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=0 repo_gpgcheck=0 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF
拉取flanel镜像
docker pull lizhenliang/flannel:v0.11.0-amd64
3、安装 kubeadm,kubelet 和 kubectl
yum list|grep kube #检查是否有kube源
yum install -y kubelet-1.17.3 kubeadm-1.17.3 kubectl-1.17.3
systemctl enable kubelet #开机启动
systemctl start kubelet #启动
查看kubelet状态:systemctl status kubelet
发现启动不起来,因为其他配置未配置,这里先不管
6、部署k8s-master
1、master 节点初始化
先查看要成为master节点的默认网卡地址:ip addr
如图下面的设置为–apiserver-advertise-address=10.0.2.15
执行命令前可能失败先复制我们准备的master_images.sh
文件
master_images.sh:
#!/bin/bash
images=(
kube-apiserver:v1.17.3
kube-proxy:v1.17.3
kube-controller-manager:v1.17.3
kube-scheduler:v1.17.3
coredns:1.6.5
etcd:3.4.3-0
pause:3.1
)
for imageName in ${images[@]} ; do
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
# docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
done
复制到这个要成为master节点的机器中
当前文件可能没有执行的权限使用命令
chmod 700 master_images.sh
执行这个文件下砸镜像
./master_images.sh
等待几分钟下载完成,执行docker images
查看下载情况
之后执行下面命令
kubeadm init \
--apiserver-advertise-address=10.0.2.15 \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version v1.17.3 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=10.244.0.0/16
可能提示swap的错误,关闭即可
或者提示
把这个设置为1即可
echo "1">/proc/sys/net/bridge/bridge-nf-call-iptables
echo "1">/proc/sys/net/bridge/bridge-nf-call-ip6tables
启动成功
由于默认拉取镜像地址k8s.gcr.io
国内无法访问,这里指定阿里云镜像仓库地址。可以手动 按照我们的 images.sh
先拉取镜像,
地址变为 registry.aliyuncs.com/google_containers
也可以。
科普:无类别域间路由(Classless Inter-Domain Routing、CIDR)是一个用于给用户分配 IP 地址以及在互联网上有效地路由 IP 数据包的对 IP 地址进行归类的方法。
拉取可能失败,需要下载镜像。
运行完成提前复制:加入集群的令牌,这会成功后先不要删除信息
2、测试 kubectl(主节点执行)
初始化成功后提示
执行一些配置文件
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
//todo
目前 master 状态为 notready。等待网络加入完成即可。
journalctl -u kubelet
7、 安装 Pod 网络插件(CNI)
$ kubectl apply -f \
https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
可能拉去失败,这里我用自己的
kube-flannel.yml
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp.flannel.unprivileged
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default
seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default
apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
spec:
privileged: false
volumes:
- configMap
- secret
- emptyDir
- hostPath
allowedHostPaths:
- pathPrefix: "/etc/cni/net.d"
- pathPrefix: "/etc/kube-flannel"
- pathPrefix: "/run/flannel"
readOnlyRootFilesystem: false
# Users and groups
runAsUser:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
fsGroup:
rule: RunAsAny
# Privilege Escalation
allowPrivilegeEscalation: false
defaultAllowPrivilegeEscalation: false
# Capabilities
allowedCapabilities: ['NET_ADMIN']
defaultAddCapabilities: []
requiredDropCapabilities: []
# Host namespaces
hostPID: false
hostIPC: false
hostNetwork: true
hostPorts:
- min: 0
max: 65535
# SELinux
seLinux:
# SELinux is unused in CaaSP
rule: 'RunAsAny'
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: flannel
rules:
- apiGroups: ['extensions']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames: ['psp.flannel.unprivileged']
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- ""
resources:
- nodes
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: flannel
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: flannel
subjects:
- kind: ServiceAccount
name: flannel
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: flannel
namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
name: kube-flannel-cfg
namespace: kube-system
labels:
tier: node
app: flannel
data:
cni-conf.json: | { "name": "cbr0", "cniVersion": "0.3.1", "plugins": [ { "type": "flannel", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true } } ] }
net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } }
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-flannel-ds-amd64
namespace: kube-system
labels:
tier: node
app: flannel
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
tier: node
app: flannel
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: beta.kubernetes.io/os
operator: In
values:
- linux
- key: beta.kubernetes.io/arch
operator: In
values:
- amd64
hostNetwork: true
tolerations:
- operator: Exists
effect: NoSchedule
serviceAccountName: flannel
initContainers:
- name: install-cni
image: quay.io/coreos/flannel:v0.11.0-amd64
command:
- cp
args:
- -f
- /etc/kube-flannel/cni-conf.json
- /etc/cni/net.d/10-flannel.conflist
volumeMounts:
- name: cni
mountPath: /etc/cni/net.d
- name: flannel-cfg
mountPath: /etc/kube-flannel/
containers:
- name: kube-flannel
image: quay.io/coreos/flannel:v0.11.0-amd64
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
resources:
requests:
cpu: "100m"
memory: "50Mi"
limits:
cpu: "100m"
memory: "50Mi"
securityContext:
privileged: false
capabilities:
add: ["NET_ADMIN"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- name: run
mountPath: /run/flannel
- name: flannel-cfg
mountPath: /etc/kube-flannel/
volumes:
- name: run
hostPath:
path: /run/flannel
- name: cni
hostPath:
path: /etc/cni/net.d
- name: flannel-cfg
configMap:
name: kube-flannel-cfg
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-flannel-ds-arm64
namespace: kube-system
labels:
tier: node
app: flannel
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
tier: node
app: flannel
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: beta.kubernetes.io/os
operator: In
values:
- linux
- key: beta.kubernetes.io/arch
operator: In
values:
- arm64
hostNetwork: true
tolerations:
- operator: Exists
effect: NoSchedule
serviceAccountName: flannel
initContainers:
- name: install-cni
image: quay.io/coreos/flannel:v0.11.0-arm64
command:
- cp
args:
- -f
- /etc/kube-flannel/cni-conf.json
- /etc/cni/net.d/10-flannel.conflist
volumeMounts:
- name: cni
mountPath: /etc/cni/net.d
- name: flannel-cfg
mountPath: /etc/kube-flannel/
containers:
- name: kube-flannel
image: quay.io/coreos/flannel:v0.11.0-arm64
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
resources:
requests:
cpu: "100m"
memory: "50Mi"
limits:
cpu: "100m"
memory: "50Mi"
securityContext:
privileged: false
capabilities:
add: ["NET_ADMIN"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- name: run
mountPath: /run/flannel
- name: flannel-cfg
mountPath: /etc/kube-flannel/
volumes:
- name: run
hostPath:
path: /run/flannel
- name: cni
hostPath:
path: /etc/cni/net.d
- name: flannel-cfg
configMap:
name: kube-flannel-cfg
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-flannel-ds-arm
namespace: kube-system
labels:
tier: node
app: flannel
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
tier: node
app: flannel
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: beta.kubernetes.io/os
operator: In
values:
- linux
- key: beta.kubernetes.io/arch