云原生Java架构 K8s+Docker+KubeSphere+DevOps
简介:摘自 尚硅谷雷锋阳老师的语雀文档
云平台
学会使用按量付费的云服务器,开发测试性价比高
私有网络VPC
和网络有关的概念,如何在云服务器开通一个集群
一个云服务器有两个IP:公网IP和私网IP
公网IP:对外暴露资源的访问,可能会发生改变,按量付费服务器每次启动可能都会发生改变 私网IP:服务器内部网卡使用的IP,需要固定不变,集群内部交互用
VPC的子网计算
VPC:私有网络、专有网络
网段的概念
将IP地址转化为二进制就是如下,每个段有八位二进制,16掩码表示掩去前16位,只后16位变化,而8位最大二进制 11111111 转化为10 进制就是 256 ,而IP包括一个零那就是255,所以此网段的变化为 192.168.0.0 ~ 192.168.255.255 有 65536 个IP
通过子网计算,实际可用为65534个
VPC的交换机
因为专有网络的可用IP太多了不好区分,单16位掩码的IP就有65534个,所以交换机的作用是用来规定专有网络下的哪些IP能用,避免专有网络使用太过混乱 在创建专有网络时同时制定或创建交换机,如下图的设定,表示创建24位掩码,指定第三段的号段,那么可用IP就在第4号段变化,将可用IP由65534个缩小到了252个,避免了混乱
重要概念
不同VPC网络下,即使私有网络IP相同,他们之间内部是无法平通的,所以一个VPC相当于一个局域网的隔离,
容器化
docker概念
差异化保存
资源隔离 ● cpu、memory资源隔离与限制 ● 访问设备隔离与限制 ● 网络隔离与限制 ● 用户、用户组隔离限制
架构
- Docker_Host:
○ 安装Docker的主机 - Docker Daemon:
○ 运行在Docker主机上的Docker后台进程 - Client:
○ 操作Docker主机的客户端(命令行、UI等) - Registry:
○ 镜像仓库 ○ Docker Hub - Images:
○ 镜像,带环境打包好的程序,可以直接启动运行 - Containers:
○ 容器,由镜像启动起来正在运行中的程序
青云服务器
centos安装docker
1、移除以前docker相关包
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
2、配置yum源
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
3、安装docker
sudo yum install -y docker-ce docker-ce-cli containerd.io
#以下是在安装k8s的时候使用 指定版本
yum install -y docker-ce-20.10.7 docker-ce-cli-20.10.7 containerd.io-1.4.6
4、启动和开机启动
systemctl enable docker --now
5、配置加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://vgcihl1j.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
docker实战
1、找镜像
docker pull nginx
镜像名:版本名(标签)
docker pull nginx:1.20.1
docker pull redis
docker pull redis:6.2.4
docker images
redis = redis:latest
docker rmi 镜像名:版本号/镜像id
2、启动容器
启动nginx应用容器,并映射88端口,测试的访问
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
【docker run 设置项 镜像名 】 镜像启动运行的命令(镜像里面默认有的,一般不会写)
docker run --name=mynginx -d --restart=always -p 88:80 nginx
docker ps
docker ps -a
docker rm 容器id/名字
docker rm -f mynginx
docker stop 容器id/名字
docker start 容器id/名字
docker update 容器id/名字 --restart=always
3、进入容器修改内容
[root@i-r686cdnl ~] docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
33040453a360 nginx "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:88->80/tcp, :::88->80/tcp mynginx
[root@i-r686cdnl ~] docker exec -it 33040453a360 /bin/sh
root@33040453a360:/bin] cd /usr/share/nginx/html
root@33040453a360:/usr/share/nginx/html] echo "<h1>hello atguigu</h1>" > index.html
docker run --name=mynginx \
-d --restart=always \
-p 88:80 \
-v /data/html:/usr/share/nginx/html:ro \
nginx
4、提交改变 将指定容器提交成新容器
[root@i-r686cdnl ~]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
33040453a360 nginx "/docker-entrypoint.…" 12 minutes ago Up 12 minutes 0.0.0.0:88->80/tcp, :::88->80/tcp mynginx
[root@i-r686cdnl ~]
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Options:
-a, --author string Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
-c, --change list Apply Dockerfile instruction to the created image
-m, --message string Commit message
-p, --pause Pause container during commit (default true)
[root@i-r686cdnl ~] docker commit -a "作者" -m "描述" 33040453a360 gugunginx:v1.0
sha256:50eecfacab35a36f8dfd3aefd205e04dfe5742e590fdc6061aaf490ecedfa3bf
[root@i-r686cdnl ~] docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
gugunginx v1.0 50eecfacab35 6 seconds ago 133MB
nginx latest 87a94228f133 9 days ago 133MB
镜像传输
docker save -o abc.tar guignginx:v1.0
docker load -i abc.tar
5、推送远程仓库 推送镜像到docker hub;应用市场
docker tag local-image:tagname new-repo:tagname
docker push new-repo:tagname
docker tag guignginx:v1.0 leifengyang/guignginx:v1.0
docker login
docker logout(推送完成镜像后退出)
docker push leifengyang/guignginx:v1.0
docker pull leifengyang/guignginx:v1.0
6、补充
docker logs 容器名/id 排错
docker exec -it 容器id /bin/bash
docker run -d -p 80:80 \
-v /data/html:/usr/share/nginx/html:ro \
-v /data/conf/nginx.conf:/etc/nginx/nginx.conf \
--name mynginx-02 \
nginx
docker cp 5eff66eec7e1:/etc/nginx/nginx.conf /data/conf/nginx.conf
docker cp /data/conf/nginx.conf 5eff66eec7e1:/etc/nginx/nginx.conf
docker进阶
部署redis
部署一个Redis+应用,尝试应用操作Redis产生数据 注意先创建好主机的文件挂载目录和配置文件
mkdir -p /data/redis/
vi redis.conf
appendonly yes
-------------------------------
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
docker run \
-v /data/redis/redis.conf:/etc/redis/redis.conf \
-v /data/redis/data:/data \
-d --name myredis \
-p 6379:6379 \
redis:latest redis-server /etc/redis/redis.conf
设置redis密码登录
vi redis.conf
requirepass 123xxx
docker restart myredis
创建Java应用
1、用redis简单的统计功能
@RestController
public class CounterController {
@Autowired
StringRedisTemplate redisTemplate;
@GetMapping("/hello")
public String count(){
Long increment = redisTemplate.opsForValue().increment("count-people");
return "有"+ increment +" 访问了页面";
}
}
2、将应用打包成镜像
以前:Java为例
- SpringBoot打包成可执行jar
- 把jar包上传给服务
- 服务器运行java -jar
现在:所有机器都安装Docker,任何应用都是镜像,所有机器都可以运行
3、怎么打包-Dockerfile
FROM openjdk:8-jdk-slim
LABEL maintainer=leifengyang
COPY target/*.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
将这两个文件打包成一个文件上传到服务器
运行Dockerfile打包成镜像,默认不用输Dockerfile,注意末尾有一个 点,表示在当前目录下工作
docker build -t java-demo:v1.0 .
3、启动容器
docker run -d -p 8080:8080 --name myjava-app java-demo:v1.0
docker logs 容器id 查看日志,容器和项目启动成功,在网络正常访问
分享镜像
docker login
docker tag java-demo:v1.0 leifengyang/java-demo:v1.0
docker push leifengyang/java-demo:v1.0
docker pull leifengyang/java-demo:v1.0
docker run -d -p 8080:8080 --name myjava-app java-demo:v1.0
Kubernetes
基础概念
简介
是什么
kubernetes具有以下特性:
- 服务发现和负载均衡
Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。 - 存储编排
Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。 - 自动部署和回滚
你可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态 更改为期望状态。例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。 - 自动完成装箱计算
Kubernetes 允许你指定每个容器所需 CPU 和内存(RAM)。 当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源。 - 自我修复
Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的 运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。 - 密钥与配置管理
Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。
Kubernetes 为你提供了一个可弹性运行分布式系统的框架。 Kubernetes 会满足你的扩展要求、故障转移、部署模式等。 例如,Kubernetes 可以轻松管理系统的 Canary 部署。
集群的方式
架构
1、工作方式 Kubernetes Cluster = N Master Node + N Worker Node:N主节点+N工作节点; N>=1
2、组件架构
1、控制平面组件(Control Plane Components) 控制平面的组件对集群做出全局决策(比如调度),以及检测和响应集群事件(例如,当不满足部署的 replicas 字段时,启动新的 pod)。 控制平面组件可以在集群中的任何节点上运行。 然而,为了简单起见,设置脚本通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行用户容器。 请参阅使用 kubeadm 构建高可用性集群 中关于多 VM 控制平面设置的示例。 kube-apiserver API 服务器是 Kubernetes 控制面的组件, 该组件公开了 Kubernetes API。 API 服务器是 Kubernetes 控制面的前端。 Kubernetes API 服务器的主要实现是 kube-apiserver。 kube-apiserver 设计上考虑了水平伸缩,也就是说,它可通过部署多个实例进行伸缩。 你可以运行 kube-apiserver 的多个实例,并在这些实例之间平衡流量。 etcd etcd 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。 您的 Kubernetes 集群的 etcd 数据库通常需要有个备份计划。 要了解 etcd 更深层次的信息,请参考 etcd 文档。 kube-scheduler 控制平面组件,负责监视新创建的、未指定运行节点(node)的 Pods,选择节点让 Pod 在上面运行。 调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。 kube-controller-manager 在主节点上运行 控制器 的组件。 从逻辑上讲,每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。 这些控制器包括: ● 节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应 ● 任务控制器(Job controller): 监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成 ● 端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入 Service 与 Pod) ● 服务帐户和令牌控制器(Service Account & Token Controllers): 为新的命名空间创建默认帐户和 API 访问令牌 cloud-controller-manager 云控制器管理器是指嵌入特定云的控制逻辑的 控制平面组件。 云控制器管理器允许您链接集群到云提供商的应用编程接口中, 并把和该云平台交互的组件与只和您的集群交互的组件分离开。 cloud-controller-manager 仅运行特定于云平台的控制回路。 如果你在自己的环境中运行 Kubernetes,或者在本地计算机中运行学习环境, 所部署的环境中不需要云控制器管理器。 与 kube-controller-manager 类似,cloud-controller-manager 将若干逻辑上独立的 控制回路组合到同一个可执行文件中,供你以同一进程的方式运行。 你可以对其执行水平扩容(运行不止一个副本)以提升性能或者增强容错能力。 下面的控制器都包含对云平台驱动的依赖: ● 节点控制器(Node Controller): 用于在节点终止响应后检查云提供商以确定节点是否已被删除 ● 路由控制器(Route Controller): 用于在底层云基础架构中设置路由 ● 服务控制器(Service Controller): 用于创建、更新和删除云提供商负载均衡器 2、Node 组件 节点组件在每个节点上运行,维护运行的 Pod 并提供 Kubernetes 运行环境。 kubelet 一个在集群中每个节点(node)上运行的代理。 它保证容器(containers)都 运行在 Pod 中。 kubelet 接收一组通过各类机制提供给它的 PodSpecs,确保这些 PodSpecs 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。 kube-proxy kube-proxy 是集群中每个节点上运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。 kube-proxy 维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信。 如果操作系统提供了数据包过滤层并可用的话,kube-proxy 会通过它来实现网络规则。否则, kube-proxy 仅转发流量本身。
准备搭建的架构图
集群搭建
创建服务器
创建vpc及其私有网络 创建三台按需付费服务器 2c4t ,指定刚创建好的vpc网络,分配三个公网IP,安全组内打开组内互信这样内部IP互通就可以绕开防火墙
ssh工具连接,指定一个做为master
一个master 两个node
docker容器化环境安装
参考上面docker安装
预备环境创建
- 一台兼容的 Linux 主机。Kubernetes 项目为基于 Debian 和 Red Hat 的 Linux 发行版以及一些不提供包管理器的发行版提供通用的指令
- 每台机器 2 GB 或更多的 RAM (如果少于这个数字将会影响你应用的运行内存)
- 2 CPU 核或更多
- 集群中的所有机器的网络彼此均能相互连接(公网和内网都可以)
○ 设置防火墙放行规则 - 节点之中不可以有重复的主机名、MAC 地址或 product_uuid。请参见这里了解更多详细信息。
○ 设置不同hostname - 开启机器上的某些端口。请参见这里 了解更多详细信息。
○ 内网互信 - 禁用交换分区。为了保证 kubelet 正常工作,你 必须 禁用交换分区。
○ 永久关闭
hostnamectl set-hostname xxxx
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system
安装集群三大件
安装kubelet、kubeadm、kubectl
cat <<EOF | sudo tee /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
exclude=kubelet kubeadm kubectl
EOF
sudo yum install -y kubelet-1.20.9 kubeadm-1.20.9 kubectl-1.20.9 --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
使用kubeadm引导启动集群
1、提前下载各个机器需要的镜像,避免因网络原因造成的安装失败
sudo tee ./images.sh <<-'EOF'
#!/bin/bash
images=(
kube-apiserver:v1.20.9
kube-proxy:v1.20.9
kube-controller-manager:v1.20.9
kube-scheduler:v1.20.9
coredns:1.7.0
etcd:3.4.13-0
pause:3.2
)
for imageName in ${images[@]} ; do
docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/$imageName
done
EOF
chmod +x ./images.sh && ./images.sh
2、初始化主节点
echo "172.31.0.2 cluster-endpoint" >> /etc/hosts
kubeadm init \
--apiserver-advertise-address=172.31.0.2 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16
初始化后返回的信息
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join cluster-endpoint:6443 --token 2n4gns.e3n0mqlip1nmbbqa \
--discovery-token-ca-cert-hash sha256:786bc6e4ac9d96e6d6764d94b16e4cd40e599669e4824ebba5a7eba31bb2a983 \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join cluster-endpoint:6443 --token epjqlx.25mfge9y4rgw1n4o \
--discovery-token-ca-cert-hash sha256:5298e8db61faebe5eca8bfc5ec788d5f9bb4bad16dbe924027d33c05416c3738
运行上面第一步,完成主节点创建
现在能用到的一些命令
kubectl get nodes
kubectl apply -f xxxx.yaml
docker ps === kubectl get pods -A
kubectl get pods -A
3、安装网络组件
curl https://docs.projectcalico.org/manifests/calico.yaml -O
kubectl apply -f calico.yaml
4、加入node节点 在子节点,运行上面初始化master节点时生成的命令,这个命令24小时内有效
kubeadm join cluster-endpoint:6443 --token 2n4gns.e3n0mqlip1nmbbqa \
--discovery-token-ca-cert-hash sha256:786bc6e4ac9d96e6d6764d94b16e4cd40e599669e4824ebba5a7eba31bb2a983
若令牌过期,主节点创建新令牌 kubeadm token create --print-join-command
等待一会查看节点准备状况,至此k8s集群准备就绪
[root@k8s-master ~] kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane,master 34m v1.20.9
k8s-node1 Ready <none> 83s v1.20.9
k8s-node2 Ready <none> 78s v1.20.9
部署dashboard
1、部署
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml
apiVersion: v1
kind: Namespace
metadata:
name: kubernetes-dashboard
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-certs
namespace: kubernetes-dashboard
type: Opaque
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-csrf
namespace: kubernetes-dashboard
type: Opaque
data:
csrf: ""
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-key-holder
namespace: kubernetes-dashboard
type: Opaque
---
kind: ConfigMap
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-settings
namespace: kubernetes-dashboard
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
verbs: ["get", "update", "delete"]
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["kubernetes-dashboard-settings"]
verbs: ["get", "update"]
- apiGroups: [""]
resources: ["services"]
resourceNames: ["heapster", "dashboard-metrics-scraper"]
verbs: ["proxy"]
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
verbs: ["get"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
rules:
- apiGroups: ["metrics.k8s.io"]
resources: ["pods", "nodes"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: kubernetesui/dashboard:v2.3.1
imagePullPolicy: Always
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
- --namespace=kubernetes-dashboard
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
httpGet:
scheme: HTTPS
path: /
port: 8443
initialDelaySeconds: 30
timeoutSeconds: 30
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
nodeSelector:
"kubernetes.io/os": linux
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
ports:
- port: 8000
targetPort: 8000
selector:
k8s-app: dashboard-metrics-scraper
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: dashboard-metrics-scraper
template:
metadata:
labels:
k8s-app: dashboard-metrics-scraper
annotations:
seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'
spec:
containers:
- name: dashboard-metrics-scraper
image: kubernetesui/metrics-scraper:v1.0.6
ports:
- containerPort: 8000
protocol: TCP
livenessProbe:
httpGet:
scheme: HTTP
path: /
port: 8000
initialDelaySeconds: 30
timeoutSeconds: 30
volumeMounts:
- mountPath: /tmp
name: tmp-volume
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
serviceAccountName: kubernetes-dashboard
nodeSelector:
"kubernetes.io/os": linux
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
volumes:
- name: tmp-volume
emptyDir: {}
2、设置访问端口
这里需要修改集群中的资源
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
将type的值改为NodePort
kubectl get svc -A |grep kubernetes-dashboard
访问: https://集群任意IP:端口
3、创建访问账号
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
kubectl apply -f dash.yaml
4、令牌访问
kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"
复制返回的密钥就能登录
核心实战
操作NameSpace
名称空间用来对资源隔离划分。默认只隔离资源,不隔离网络
创建删除名称空间
kubectl create ns hello
kubectl delete ns hello
通过文件创建名称空间
apiVersion: v1
kind: Namespace
metadata:
name: hello
通过文件创建的ns也通过文件删除
kubectl apply -f hello.yml
kubectl delete -f hello.yml
理解Pod
运行中的一组 容器,Pod是kubernetes中应用的最小单位。一个pod中可能包含多个docker的容器
查看pod能看到ready, 准备好的容器数量/总共的容器数量
kubectl命令行方式创建第一个pod
kubectl run mynginx --image=nginx
kubectl get pod
kubectl describe pod 你自己的Pod名字
kubectl delete pod Pod名字
kubectl logs Pod名字
kubectl get pod -owide
curl 192.168.169.136
以配置文件创建
apiVersion: v1
kind: Pod
metadata:
labels:
run: mynginx
name: mynginx
spec:
containers:
- image: nginx
name: mynginx
kubectl apply -f 配置文件
kubectl delete -f 配置文件
可视化方式操作pod和pod细节
可视化控制台直接查看容器日志,和进入容器的内部相当于 docker exec -it /bin/bash
kubectl exec -it myapp -- /bin/bash
kubectl get pod -owide
curl 192.168.169.136
一个pod中启动两个容器
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp
name: myapp
spec:
containers:
- image: nginx
name: nginx
- image: tomcat:8.5.68
name: tomcat
此时的应用还不能外部访问,只能内部互相调用
使用Deployment部署应用
控制Pod,使Pod拥有多副本,自愈,扩缩容等能, 即使主动执行删除pod指令kubectl delete pod xxx ,集群也会恢复这个pod,这就是自愈
kubectl run mynginx --image=nginx
kubectl create deployment mytomcat --image=tomcat:8.5.68
多副本部署
kubectl create deployment my-dep --image=nginx --replicas=3
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: my-dep
name: my-dep
spec:
replicas: 3
selector:
matchLabels:
app: my-dep
template:
metadata:
labels:
app: my-dep
spec:
containers:
- image: nginx
name: nginx
查看部署 kubectl get deploy xxxx
Deployment扩缩容
kubectl scale --replicas=5 deployment/my-dep
自愈&故障转移
启动了一个deployment有三个容器部署,其中node2两个,node1一个
我们关机node2服务器,集群默认5分钟后才会做故障转移工作
kubectl get pod -owide
kubectl get pod -w
4、滚动更新 不停机更新,更改deploy对部署镜像,集群就会对deploy进行更新,老的镜像容器不回立马停机,而是等到新镜像容器启动成功后再替换掉老镜像容器,完成了不停机更新、滚动部署
kubectl get deploy my-dep -oyaml
kubectl set image deployment/my-dep nginx=nginx:1.16.1 --record
kubectl rollout status deployment/my-dep
5、版本回退
kubectl rollout history deployment/my-dep
kubectl rollout history deployment/my-dep --revision=2
kubectl rollout undo deployment/my-dep
kubectl rollout undo deployment/my-dep --to-revision=2
kubectl get deploy/my-dep -oyaml|grep image
除了Deployment,k8s还有 StatefulSet 、DaemonSet 、Job 等 类型资源。我们都称为 工作负载。 有状态应用使用 StatefulSet 部署,无状态应用使用 Deployment 部署 https://kubernetes.io/zh/docs/concepts/workloads/controllers/
其他工作负载
服务网络
Service
将一组 Pods 公开为网络服务的抽象方法。
kubectl expose deployment my-dep --port=8000 --target-port=80 --type=ClusterIP
kubectl get svc
kubectl get pod -l app=my-dep
服务器内部就可以用暴露的IP访问 集群内部额外的还能使用service名.命名空间.svc:端口
curl my-dep.default.svc:8000
但是此时,集群外,服务器无法直接用service名访问
service的服务发现,下线pod 流量会自动转到其他service的pod不影响访问,再加入pod也会自动负载均衡
1、ClusterIP
kubectl expose deployment my-dep --port=8000 --target-port=80 --type=ClusterIP
2、NodePort
kubectl expose deployment my-dep --port=8000 --target-port=80 --type=NodePort
先删除之前的clusterip type,暴露为nodeport。随机分配一个端口31586 ,8000用作集群内访问,随机端口用作公网访问
Ingress
1、安装
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml
vi deploy.yaml
image: k8s.gcr.io/ingress-nginx/controller:v0.46.0@sha256:52f0058bed0a17ab0fb35628ba97e8d52b5d32299fbc03cc0f6c7b9ff036b61a
----改为
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.0
kubectl get pod,svc -n ingress-nginx
安装完成后
kubectl get svc -A
ingress-nginx ingress-nginx-controller NodePort 10.96.189.29 <none> 80:31735/TCP,443:31607/TCP 88s
30000 - 32767
任意集群服务器的公网IP都能通过这两个端口访问到ingress
Ingress的使用
官网地址:https://kubernetes.github.io/ingress-nginx/ 就是nginx做的
应用如下yaml,准备好测试环境
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-server
spec:
replicas: 2
selector:
matchLabels:
app: hello-server
template:
metadata:
labels:
app: hello-server
spec:
containers:
- name: hello-server
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-server
ports:
- containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-demo
name: nginx-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-demo
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- image: nginx
name: nginx
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-demo
name: nginx-demo
spec:
selector:
app: nginx-demo
ports:
- port: 8000
protocol: TCP
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
labels:
app: hello-server
name: hello-server
spec:
selector:
app: hello-server
ports:
- port: 8000
protocol: TCP
targetPort: 9000
此yml文件的动作为,前两部分为:产生了两个deployment,每个部署了两个pod。 后两部分,产生了两个service,service selector分别选中了之前两次部署的pod,新开端口port映射到pod的端口targetPort,做到负载均衡
deployment :部署的作用是做到pod的自愈 service:作用是负载均衡
添加Ingress的域名访问规则,相当于Spring cloud的GateWay了
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-host-bar
spec:
ingressClassName: nginx
rules:
- host: "hello.atguigu.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-server
port:
number: 8000
- host: "demo.atguigu.com"
http:
paths:
- pathType: Prefix
path: "/nginx"
backend:
service:
name: nginx-demo
port:
number: 8000
修改本机host文件,因为集群内任意服务器的公网IP都能访问到集群 此时通过
kubectl get svc -A
http://hello.atguigu.com:31735/
http://demo.atguigu.com:31735/nginx
成功负载均衡的访问到 service下的pod
Ingress的路径重写
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: ingress-host-bar
spec:
ingressClassName: nginx
rules:
- host: "hello.atguigu.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-server
port:
number: 8000
- host: "demo.atguigu.com"
http:
paths:
- pathType: Prefix
path: "/nginx(/|$)(.*)"
backend:
service:
name: nginx-demo
port:
number: 8000
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-limit-rate
annotations:
nginx.ingress.kubernetes.io/limit-rps: "1"
spec:
ingressClassName: nginx
rules:
- host: "haha.atguigu.com"
http:
paths:
- pathType: Exact
path: "/"
backend:
service:
name: nginx-demo
port:
number: 8000
Ingress网络模型总结
存储抽象
环境准备
1、所有节点
yum install -y nfs-utils
2、主节点
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
mkdir -p /nfs/data
systemctl enable rpcbind --now
systemctl enable nfs-server --now
exportfs -r
3、从节点
showmount -e 172.31.0.2
mkdir -p /nfs/data
mount -t nfs 172.31.0.2:/nfs/data /nfs/data
echo "hello nfs server" > /nfs/data/test.txt
4、Deployment使用NFS挂载
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-pv-demo
name: nginx-pv-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-pv-demo
template:
metadata:
labels:
app: nginx-pv-demo
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
nfs:
server: 172.31.0.2
path: /nfs/data/nginx-pv
创建时
kubectl get pod -A
kubectl describe NAME
发现容器创建错误,没有指定目录,我们删除本次deployment,重新部署。注意先创建挂载目录
PV&PVC
PV:持久卷(Persistent Volume),将应用需要持久化的数据保存到指定位置(场地) PVC:持久卷申明(Persistent Volume Claim),申明需要使用的持久卷规格(场地申明)
PVC会自动合理的选择大小合适的PV
1、创建pv池
mkdir -p /nfs/data/01
mkdir -p /nfs/data/02
mkdir -p /nfs/data/03
创建PV
文件分成了三块所以会申明三个pv,
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01-10m
spec:
capacity:
storage: 10M
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/01
server: 172.31.0.2
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv02-1gi
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/02
server: 172.31.0.2
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv03-3gi
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/03
server: 172.31.0.2
查看创建情况
kubectl get persistentvolume(pv)
2、PVC创建与绑定 创建pvc
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 200Mi
storageClassName: nfs
实际使用中还是pod不再绑定nfs而是绑定pvc 创建Pod绑定PVC
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy-pvc
name: nginx-deploy-pvc
spec:
replicas: 2
selector:
matchLabels:
app: nginx-deploy-pvc
template:
metadata:
labels:
app: nginx-deploy-pvc
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: nginx-pvc
kubectl exec -ti nginx-deploy-pvc-79fc8558c7-hmhq2 /bin/bash
ConfigMap
抽取应用配置,并且可以自动更新
redis示例
1、把预先创建好的配置文件设置为配置集
kubectl create cm redis-conf --from-file=redis.conf
kubectl get cm redis-conf -oyml 获取到生成的配置文件内容
apiVersion: v1
data:
redis.conf: |
appendonly yes
kind: ConfigMap
metadata:
name: redis-conf
namespace: default
2、创建Pod
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
command:
- redis-server
- "/redis-master/redis.conf"
ports:
- containerPort: 6379
volumeMounts:
- mountPath: /data
name: data
- mountPath: /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap:
name: redis-conf
items:
- key: redis.conf
path: redis.conf
3、检查默认配置
kubectl exec -it redis -- redis-cli
127.0.0.1:6379> CONFIG GET appendonly
127.0.0.1:6379> CONFIG GET requirepass
4、修改ConfigMap
kubectl edit cm redis-conf
apiVersion: v1
kind: ConfigMap
metadata:
name: example-redis-config
data:
redis-config: |
appendonly yes
requirepass 123123
再次检查配置 有些配置需要重启pod才会生效
Secret
Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在 secret 中比放在 Pod 的定义或者 容器镜像 中来说更加安全和灵活。
kubectl create secret docker-registry leifengyang-docker \
--docker-username=leifengyang \
--docker-password=Lfy123456 \
--docker-email=534096094@qq.com
kubectl create secret docker-registry regcred \
--docker-server=<你的镜像仓库服务器> \
--docker-username=<你的用户名> \
--docker-password=<你的密码> \
--docker-email=<你的邮箱地址>
apiVersion: v1
kind: Pod
metadata:
name: private-nginx
spec:
containers:
- name: private-nginx
image: leifengyang/guignginx:v1.0
imagePullSecrets:
- name: leifengyang-docker
end
|