云原生Java架构实战 K8s+Docker+KubeSphere+DevOps(上)
云原生Java架构 K8s+Docker+KubeSphere+DevOps
- 云平台
- 私有网络VPC
- VPC的子网计算
- VPC的交换机
- 重要概念
- 容器化
- docker概念
- 青云服务器
- centos安装docker
- docker实战
- docker进阶
- 部署redis
- 创建Java应用
- Kubernetes
- 基础概念
- 简介
- 集群的方式
- 集群搭建
- 创建服务器
- docker容器化环境安装
- 预备环境创建
- 安装集群三大件
- 使用kubeadm引导启动集群
- 部署dashboard
- 核心实战
- 操作NameSpace
- 理解Pod
- 可视化方式操作pod和pod细节
- 使用Deployment部署应用
- Deployment扩缩容
- 自愈&故障转移
- 服务网络
- Ingress
- Ingress的使用
- 存储抽象
- 环境准备
- PV&PVC
- ConfigMap
- Secret
- end
简介:摘自 尚硅谷雷锋阳老师的语雀文档
云平台
学会使用按量付费的云服务器,开发测试性价比高
私有网络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.1docker pull redis #下载最新
docker pull redis:6.2.4## 下载来的镜像都在本地
docker images #查看所有镜像redis = redis:latestdocker rmi 镜像名:版本号/镜像id
2、启动容器
启动nginx应用容器,并映射88端口,测试的访问
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]【docker run 设置项 镜像名 】 镜像启动运行的命令(镜像里面默认有的,一般不会写)# -d:后台运行
# --restart=always: 开机自启
docker run --name=mynginx -d --restart=always -p 88:80 nginx
# 端口映射 [-p 主机端口:容器端口]# 查看正在运行的容器
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# -v 主机目录:容器目录:读写权限
# 修改页面只需要去 主机的 /data/html
4、提交改变
将指定容器提交成新容器
[root@i-r686cdnl ~]# docker ps
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 ~]# docker commit --helpUsage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]Create a new image from a container's changesOptions:-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 hub
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 经常修改nginx配置文件
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...]#redis使用自定义配置文件启动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-server 以/etc/redis/redis.conf 配置文件加载启动
设置redis密码登录
vi redis.conf
requirepass 123xxx
docker restart myredis #重启redis
创建Java应用
1、用redis简单的统计功能
@RestController
public class CounterController {@AutowiredStringRedisTemplate 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 #基础运行环境,相当去掉了 duoker pull
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 hub
docker login#给旧镜像起名
docker tag java-demo:v1.0 leifengyang/java-demo:v1.0# 推送到docker hub
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# 将 SELinux 设置为 permissive 模式(相当于将其禁用)禁用安全模式
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config#关闭swap # free -m 查看swap
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab#允许 iptables 检查桥接流量
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOFcat <<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.gpghttp://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、提前下载各个机器需要的镜像,避免因网络原因造成的安装失败
# 生成一个sh文件,循环下载定义的镜像
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、初始化主节点
#所有机器添加master域名映射,以下需要修改为自己的master节点的私网IP
# 让所有节点知道主节点的位置IP
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/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/configAlternatively, if you are the root user, you can run:export KUBECONFIG=/etc/kubernetes/admin.conf# 还应该再来部署一个pod网络插件,这个插件将集群之间的机器打通互相通讯
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 # 还可以加入任意多的工作节点,运行下面的kubeadm加入子节点
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
# 运行中的应用在docker里面叫容器,在k8s里面叫Pod
kubectl get pods -A
3、安装网络组件
curl https://docs.projectcalico.org/manifests/calico.yaml -Okubectl 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
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.apiVersion: v1
kind: Namespace
metadata:name: kubernetes-dashboard---apiVersion: v1
kind: ServiceAccount
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard---kind: Service
apiVersion: v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
spec:ports:- port: 443targetPort: 8443selector:k8s-app: kubernetes-dashboard---apiVersion: v1
kind: Secret
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard-certsnamespace: kubernetes-dashboard
type: Opaque---apiVersion: v1
kind: Secret
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard-csrfnamespace: kubernetes-dashboard
type: Opaque
data:csrf: ""---apiVersion: v1
kind: Secret
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard-key-holdernamespace: kubernetes-dashboard
type: Opaque---kind: ConfigMap
apiVersion: v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard-settingsnamespace: kubernetes-dashboard---kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
rules:# Allow Dashboard to get, update and delete Dashboard exclusive secrets.- apiGroups: [""]resources: ["secrets"]resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]verbs: ["get", "update", "delete"]# Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.- apiGroups: [""]resources: ["configmaps"]resourceNames: ["kubernetes-dashboard-settings"]verbs: ["get", "update"]# Allow Dashboard to get metrics.- 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-dashboardname: kubernetes-dashboard
rules:# Allow Metrics Scraper to get metrics from the Metrics server- apiGroups: ["metrics.k8s.io"]resources: ["pods", "nodes"]verbs: ["get", "list", "watch"]---apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
roleRef:apiGroup: rbac.authorization.k8s.iokind: Rolename: kubernetes-dashboard
subjects:- kind: ServiceAccountname: kubernetes-dashboardnamespace: kubernetes-dashboard---apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: kubernetes-dashboard
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: kubernetes-dashboard
subjects:- kind: ServiceAccountname: kubernetes-dashboardnamespace: kubernetes-dashboard---kind: Deployment
apiVersion: apps/v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
spec:replicas: 1revisionHistoryLimit: 10selector:matchLabels:k8s-app: kubernetes-dashboardtemplate:metadata:labels:k8s-app: kubernetes-dashboardspec:containers:- name: kubernetes-dashboardimage: kubernetesui/dashboard:v2.3.1imagePullPolicy: Alwaysports:- containerPort: 8443protocol: TCPargs:- --auto-generate-certificates- --namespace=kubernetes-dashboard# Uncomment the following line to manually specify Kubernetes API server Host# If not specified, Dashboard will attempt to auto discover the API server and connect# to it. Uncomment only if the default does not work.# - --apiserver-host=http://my-address:portvolumeMounts:- name: kubernetes-dashboard-certsmountPath: /certs# Create on-disk volume to store exec logs- mountPath: /tmpname: tmp-volumelivenessProbe:httpGet:scheme: HTTPSpath: /port: 8443initialDelaySeconds: 30timeoutSeconds: 30securityContext:allowPrivilegeEscalation: falsereadOnlyRootFilesystem: truerunAsUser: 1001runAsGroup: 2001volumes:- name: kubernetes-dashboard-certssecret:secretName: kubernetes-dashboard-certs- name: tmp-volumeemptyDir: {}serviceAccountName: kubernetes-dashboardnodeSelector:"kubernetes.io/os": linux# Comment the following tolerations if Dashboard must not be deployed on mastertolerations:- key: node-role.kubernetes.io/mastereffect: NoSchedule---kind: Service
apiVersion: v1
metadata:labels:k8s-app: dashboard-metrics-scrapername: dashboard-metrics-scrapernamespace: kubernetes-dashboard
spec:ports:- port: 8000targetPort: 8000selector:k8s-app: dashboard-metrics-scraper---kind: Deployment
apiVersion: apps/v1
metadata:labels:k8s-app: dashboard-metrics-scrapername: dashboard-metrics-scrapernamespace: kubernetes-dashboard
spec:replicas: 1revisionHistoryLimit: 10selector:matchLabels:k8s-app: dashboard-metrics-scrapertemplate:metadata:labels:k8s-app: dashboard-metrics-scraperannotations:seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'spec:containers:- name: dashboard-metrics-scraperimage: kubernetesui/metrics-scraper:v1.0.6ports:- containerPort: 8000protocol: TCPlivenessProbe:httpGet:scheme: HTTPpath: /port: 8000initialDelaySeconds: 30timeoutSeconds: 30volumeMounts:- mountPath: /tmpname: tmp-volumesecurityContext:allowPrivilegeEscalation: falsereadOnlyRootFilesystem: truerunAsUser: 1001runAsGroup: 2001serviceAccountName: kubernetes-dashboardnodeSelector:"kubernetes.io/os": linux# Comment the following tolerations if Dashboard must not be deployed on mastertolerations:- key: node-role.kubernetes.io/mastereffect: NoSchedulevolumes:- name: tmp-volumeemptyDir: {}
2、设置访问端口
这里需要修改集群中的资源
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
将type的值改为NodePort
kubectl get svc -A |grep kubernetes-dashboard
## 找到端口,在安全组放行
访问: https://集群任意IP:端口
3、创建访问账号
#创建访问账号,准备一个yaml文件; vi dash.yaml
apiVersion: v1
kind: ServiceAccount
metadata:name: admin-usernamespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: admin-user
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: cluster-admin
subjects:
- kind: ServiceAccountname: admin-usernamespace: 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
# 运行一个容器名字为mynginx 以 镜像nginx
kubectl run mynginx --image=nginx# 查看default名称空间的Pod
kubectl get pod
# 描述
kubectl describe pod 你自己的Pod名字
# 删除
kubectl delete pod Pod名字
# 查看Pod的运行日志
kubectl logs Pod名字# 每个Pod - k8s都会分配一个ip
kubectl get pod -owide
# 使用Pod的ip+pod里面运行容器的端口
curl 192.168.169.136# 集群中的任意一个机器以及任意的应用都能通过Pod分配的ip来访问这个Pod
以配置文件创建
apiVersion: v1
kind: Pod
metadata:labels:run: mynginxname: mynginx
# namespace: default
spec:containers:- image: nginxname: mynginx
kubectl apply -f 配置文件
kubectl delete -f 配置文件
可视化方式操作pod和pod细节
可视化控制台直接查看容器日志,和进入容器的内部相当于 docker exec -it /bin/bash
# 进入容器,交互模式
kubectl exec -it myapp -- /bin/bash
# 每个Pod - k8s都会分配一个ip
kubectl get pod -owide
# 使用Pod的ip+pod里面运行容器的端口;集群内访问
curl 192.168.169.136
一个pod中启动两个容器
apiVersion: v1
kind: Pod
metadata:labels:run: myappname: myapp
spec:containers:- image: nginxname: nginx- image: tomcat:8.5.68name: tomcat
此时的应用还不能外部访问,只能内部互相调用
使用Deployment部署应用
控制Pod,使Pod拥有多副本,自愈,扩缩容等能,
即使主动执行删除pod指令kubectl delete pod xxx
,集群也会恢复这个pod,这就是自愈
# 清除所有Pod,比较下面两个命令有何不同效果?
kubectl run mynginx --image=nginxkubectl 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-depname: my-dep
spec:replicas: 3selector:matchLabels:app: my-deptemplate:metadata:labels:app: my-depspec:containers:- image: nginxname: nginx
查看部署
kubectl get deploy xxxx
Deployment扩缩容
kubectl scale --replicas=5 deployment/my-dep
自愈&故障转移
启动了一个deployment有三个容器部署,其中node2两个,node1一个
我们关机node2服务器,集群默认5分钟后才会做故障转移工作
# 查看pod详细信息
kubectl get pod -owide# 监控pod
kubectl get pod -w
4、滚动更新
不停机更新,更改deploy对部署镜像,集群就会对deploy进行更新,老的镜像容器不回立马停机,而是等到新镜像容器启动成功后再替换掉老镜像容器,完成了不停机更新、滚动部署
# 获取deploy部署的 yaml信息,详细查看具体用的什么镜像
kubectl get deploy my-dep -oyaml# 修改dep的镜像,修改完成后立即开始滚动部署
kubectl set image deployment/my-dep nginx=nginx:1.16.1 --recordkubectl 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# 获取部署的信息以yml输出 筛选image
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 公开为网络服务的抽象方法。
#暴露Deploy 指定外部端口8000映射至集群内部端口80
kubectl expose deployment my-dep --port=8000 --target-port=80 --type=ClusterIP
# 查询service暴露的ip
kubectl get svc#使用标签检索Pod
kubectl get pod -l app=my-dep
服务器内部就可以用暴露的IP访问
集群内部额外的还能使用service名.命名空间.svc:端口
curl my-dep.default.svc:8000
但是此时,集群外,服务器无法直接用service名访问
service的服务发现,下线pod 流量会自动转到其他service的pod不影响访问,再加入pod也会自动负载均衡
1、ClusterIP
# 等同于没有可以不加 --type 默认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#将323行的镜像地址改为阿里云镜像地址
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# 最后别忘记把svc暴露的端口要放行
安装完成后
# ingress的安装会产生一个service,ingress要承接所有的流量,
# 所以产生一个service对外暴露承接流量的端口
# 查看svc详细信息
kubectl get svc -Aingress-nginx ingress-nginx-controller NodePort 10.96.189.29 <none> 80:31735/TCP,443:31607/TCP 88s# 暴露了http访问的80和https访问的443端口,并随机映射到集群内nodeport端口
# nodeport的端口范围在
30000 - 32767
任意集群服务器的公网IP都能通过这两个端口访问到ingress
Ingress的使用
官网地址:https://kubernetes.github.io/ingress-nginx/
就是nginx做的
应用如下yaml,准备好测试环境
apiVersion: apps/v1
kind: Deployment
metadata:name: hello-server
spec:replicas: 2selector:matchLabels:app: hello-servertemplate:metadata:labels:app: hello-serverspec:containers:- name: hello-serverimage: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-serverports:- containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-demoname: nginx-demo
spec:replicas: 2selector:matchLabels:app: nginx-demotemplate:metadata:labels:app: nginx-demospec:containers:- image: nginxname: nginx
---
apiVersion: v1
kind: Service
metadata:labels:app: nginx-demoname: nginx-demo
spec:selector:app: nginx-demoports:- port: 8000protocol: TCPtargetPort: 80
---
apiVersion: v1
kind: Service
metadata:labels:app: hello-servername: hello-server
spec:selector:app: hello-serverports:- port: 8000protocol: TCPtargetPort: 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: nginxrules:- host: "hello.atguigu.com"http:paths:- pathType: Prefixpath: "/"backend:service:name: hello-serverport:number: 8000- host: "demo.atguigu.com"http:paths:- pathType: Prefixpath: "/nginx" # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404backend:service:name: nginx-demo ## java,比如使用路径重写,去掉前缀nginxport:number: 8000
修改本机host文件,因为集群内任意服务器的公网IP都能访问到集群
此时通过
# 查看Ingress的暴露端口来访问Ingress
kubectl get svc -Ahttp://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: /$2name: ingress-host-bar
spec:ingressClassName: nginxrules:- host: "hello.atguigu.com"http:paths:- pathType: Prefixpath: "/"backend:service:name: hello-serverport:number: 8000- host: "demo.atguigu.com"http:paths:- pathType: Prefixpath: "/nginx(/|$)(.*)" #(路径重写) 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404backend:service:name: nginx-demo ## java,比如使用路径重写,去掉前缀nginxport:number: 8000
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress-limit-rateannotations:nginx.ingress.kubernetes.io/limit-rps: "1"
spec:ingressClassName: nginxrules:- host: "haha.atguigu.com"http:paths:- pathType: Exactpath: "/"backend:service:name: nginx-demoport:number: 8000
Ingress网络模型总结
存储抽象
环境准备
1、所有节点
#所有机器安装
yum install -y nfs-utils
2、主节点
#nfs主节点暴露/nfs/data/ 目录 *所有人。 非安全、读写
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、从节点
# 查看主节点挂载详情 主节点IP
showmount -e 172.31.0.2#执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount
mkdir -p /nfs/datamount -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-demoname: nginx-pv-demo
spec:replicas: 2selector:matchLabels:app: nginx-pv-demotemplate:metadata:labels:app: nginx-pv-demospec:containers:- image: nginxname: nginxvolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlnfs:server: 172.31.0.2path: /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池
#nfs主节点
mkdir -p /nfs/data/01
mkdir -p /nfs/data/02
mkdir -p /nfs/data/03
创建PV
文件分成了三块所以会申明三个pv,
apiVersion: v1
kind: PersistentVolume # 资源类型,pv
metadata:name: pv01-10m #别名
spec:capacity:storage: 10M #限制容量大小accessModes:- ReadWriteMany #读写模式 可读、写、多节点storageClassName: nfs # class别名nfs:path: /nfs/data/01server: 172.31.0.2 # 当前节点地址 master
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv02-1gi
spec:capacity:storage: 1GiaccessModes:- ReadWriteManystorageClassName: nfsnfs:path: /nfs/data/02server: 172.31.0.2
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv03-3gi
spec:capacity:storage: 3GiaccessModes:- ReadWriteManystorageClassName: nfsnfs:path: /nfs/data/03server: 172.31.0.2
查看创建情况
kubectl get persistentvolume(pv)
2、PVC创建与绑定
创建pvc
kind: PersistentVolumeClaim
apiVersion: v1
metadata:name: nginx-pvc
spec:accessModes:- ReadWriteManyresources:requests:storage: 200MistorageClassName: nfs
实际使用中还是pod不再绑定nfs而是绑定pvc
创建Pod绑定PVC
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-deploy-pvcname: nginx-deploy-pvc
spec:replicas: 2selector:matchLabels:app: nginx-deploy-pvctemplate:metadata:labels:app: nginx-deploy-pvcspec:containers:- image: nginxname: nginxvolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes: # 这里指定pvc- name: htmlpersistentVolumeClaim:claimName: nginx-pvc
# 修改挂载卷的内容后,进入容器查看内容是否一同变化
kubectl exec -ti nginx-deploy-pvc-79fc8558c7-hmhq2 /bin/bash
ConfigMap
抽取应用配置,并且可以自动更新
redis示例
1、把预先创建好的配置文件设置为配置集
# 创建配置,redis保存到k8s的etcd;
kubectl create cm redis-conf --from-file=redis.conf
kubectl get cm redis-conf -oyml
获取到生成的配置文件内容
apiVersion: v1
data: #data是所有真正的数据,key:默认是文件名 value:配置文件的内容redis.conf: |appendonly yes
kind: ConfigMap
metadata:name: redis-confnamespace: default
2、创建Pod
apiVersion: v1
kind: Pod
metadata:name: redis
spec:containers:- name: redisimage: rediscommand:- redis-server- "/redis-master/redis.conf" #指的是redis容器内部的位置ports:- containerPort: 6379volumeMounts:- mountPath: /dataname: data- mountPath: /redis-mastername: configvolumes:- name: dataemptyDir: {}- name: configconfigMap:name: redis-confitems:- key: redis.confpath: redis.conf
3、检查默认配置
kubectl exec -it redis -- redis-cli127.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 yesrequirepass 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-nginximage: leifengyang/guignginx:v1.0imagePullSecrets: # 指定存储好的secret- name: leifengyang-docker
end
云原生Java架构实战 K8s+Docker+KubeSphere+DevOps(上)相关推荐
- 云原生Java架构师(五)Kubernetes上安装KubeSphere
目录 一.简介 二. 安装流程 三.安装Docker 四.安装 Kubernetes 4.1 准备基础环境 4.2 安装kubelet.kubeadm.kubectl 4.3 初始化master节点 ...
- 【尚硅谷云原生Java架构师的第一课 4 2021-09-28】KubeSphere三种安装,docker,k8s,nfs安装,metrics。KubeKey一键单 多节点安装。
1.KubeSphere https://www.yuque.com/leifengyang/oncloud/gz1sls 介绍 sphere 英 /sfɪə(r)/ n. (活动.兴趣.专业知识的) ...
- K8s+Docker+KubeSphere+DevOps
云原生实战笔记 云平台核心 1. 为什么用云平台 1.1 公有云 1.2 私有云 2. 核心构架 2.1 所需软件 2.2 基础概念 Docker基本概念 1. 解决的问题 1.1 统一标准 1.2 ...
- 云原生Java架构师——KubeSphere DevOps流水线部署RuoyiCloud
目录 一.简介 二.代码 三.monitor监控服务流水线(先推送一个服务把整个流程走完) 3.1 创建流水线 3.2 拉取代码 3.3 项目编译 3.4 构建镜像 3.5 推送镜像仓库 3.6 mo ...
- 云原生Java架构师的第一课阿里云部署-KubeSphere平台安装
1.KubeSphere简介 KubeSphere官网 KubeSphere 是在 Kubernetes 之上构建的以应用为中心的多租户容器管理平台,支持部署和运行在任何基础设施之上,提供简单易用的操 ...
- 【Kubernetes 企业项目实战】05、基于云原生分布式存储 Ceph 实现 K8s 数据持久化(下)
目录 一.K8s 对接 ceph rbd 实现数据持久化 1.1 k8s 安装 ceph 1.2 创建 pod 挂载 ceph rbd 二.基于 ceph rbd 生成 pv 2.1 创建 ceph- ...
- 云原生基础架构的最佳状态,就是没有架构?
云栖号资讯:[点击查看更多行业资讯] 在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 云原生基础架构是通向云原生时代的基石,对于很多架构师来说,上云之后,架构为什么成为了云原生架构而不 ...
- 【云原生之kubernetes实战】在k8s环境下部署OneNav个人书签工具
[云原生之kubernetes实战]在k8s环境下部署OneNav个人书签工具 一.OneNav介绍 1.OneNav简介 2.OneNav特点 二.检查本地k8s环境 1.检查工作节点状态 2.检查 ...
- 【云原生之kubernetes实战】在k8s环境下部署Homepage个人导航页
[云原生之kubernetes实战]在k8s环境下部署Homepage个人导航页 一.Homepage简介 二.检查本地k8s环境 1.检查工作节点状态 2.检查系统pod状态 三.安装docker- ...
最新文章
- 选择排序算法流程图_C#实现——十大排序算法之选择排序
- centos打显卡驱动命令_CentOS7显卡驱动问题
- 如何修炼成某一领域的高手
- 【重复制造精讲】3、成本收集
- MSDN演练时发现的SqlServer2005数据库连接问题
- linux ulimit 永久生效设置方法
- 【原】浅谈KL散度(相对熵)在用户画像中的应用
- 中职计算机专业学Excel,2013年中职计算机应用专业中文Excel电子表格处理实际操作练习.doc...
- Exchange 2013 创建发送连接器
- spring与spring mvc
- r语言nonzerocoef函数_R语言如何做COX回归分析和nomogram?
- 关于linux的最新问题合集
- 性能之殇:从冯·诺依曼瓶颈谈起
- 如何缓解焦虑?做好这5件事,让你不再焦虑
- 数据分析----jupyter工具使用指导
- 32位系统的X86到底能支持多大内存
- 【 数据分析概述与职业操守】——CDA level1
- 23种设计模式-单一原则
- 场内场外交易成本_2分钟搞懂场内场外基金
- 前端面试笔试错题指南(四)