GPU-server
构建GPU服务器的容器技术:Docker
远程登陆:SSH(局域网)
Hole : 使用Holer服务端软件搭建Holer服务,通过Holer客户端软件经自己服务器实现公网访问。
容器管理:DaoCloud - DCS
Docker
容器的本质是进程
Docker本身并不是容器,它是创建容器的工具,是应用容器引擎。
Docker技术的三大核心概念,分别是:
- 镜像(Image)
- 容器(Container)
- 仓库(Repository)
安装
#安装docker
curl -sSL https://get.daocloud.io/docker | sh
#安装nvidia-docker : https://github.com/NVIDIA/nvidia-docker
# Add the package repositories
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker
#非root用户身份管理
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
#配置docker自启动
sudo systemctl enable docker
命令
#info
docker info
###################
#从dockerfile构建image
docker build -t <name>:<tag> dockerfile_path
#从container构建image
docker commit container <images-name>:<tag>
#拉取镜像
docker pull tensorflow:latest
#查看image
docker images
#导出\导入镜像(优先)
docker save -o <name>.tar.gz <image-name>
docker load -i <name>.tar.gz
#导出\导入容器(导入后cuda 失效)
docekr export -o <name>.tar.gz <container-name>
docker import <name>.tar.gz <images-name>:<tag>
####################
#创建container
docker run -ti \
--gpus all \
-p 6000:22 \
--name <name> \
-v server_dir : container_dir :ro \
-w container_dir
<image>
bash
#查看container
docker ps -a
#进入container ,attach可以带上--sig-proxy=false来确保CTRL-D或CTRL-C不会关闭容器
docker attach <container-name>
#在运行的容器中执行命令。-d 后台运行;-i 保持STDIN打开;-t 分配伪终端
#可用于多终端,作用同tmux
docker exec -ti <container-name> bash
#查看容器中运行的进程信息
docker top <container-name>
#查看端口映射
docker port <contain-name>
#容器与主机之间的数据拷贝
docker cp container:path host-path
镜像加速
# 修改 /etc/docker/daemon.json 文件(如果没有,则创建)
vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.cn-hangzhou.aliyuncs.com"],
"registry-mirrors": ["https://registry.docker-cn.com"],
"registry-mirrors": ["https://mirror.ccs.tencentyun.com"],
"registry-mirrors": ["http://f1361db2.m.daocloud.io"]
}
systemctl daemon-reload
systemctl restart docker
systemctl start kubelet # 假设您安装了 kubenetes
docker info
Docker-compose
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.
使用撰写三步骤:
-
定义
Dockerfile
或者镜像# syntax=docker/dockerfile:1 FROM python:3.7-alpine WORKDIR /code ENV FLASK_APP=app.py ENV FLASK_RUN_HOST=0.0.0.0 RUN apk add --no-cache gcc musl-dev linux-headers COPY requirements.txt requirements.txt RUN pip install -r requirements.txt EXPOSE 5000 COPY . . CMD ["flask", "run"]
-
撰写
docker-compose.yml
version: "3.9" services: web: build: . ports: - "5000:5000" volumes: - .:/code environment: # 设置环境变量 ,就像docker run -e VARIABLE=VALUE FLASK_ENV: development redis: image: "redis:alpine" volumes: logvolume01: {}
# Jenkins、Nginx的示例
version: '3'
services:
docker_jenkins:
user: root
restart: always
image: jenkinsci/blueocean
container_name: jenkins
ports:
- 8080:8080
- 50000:50000
volumes:
- /home/jenkins/jenkins_home/:/var/jenkins_name
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker
- /usr/local/bin/docker-compose:/usr/local/bin/docker-compose
docker_nginx:
user: root
restart: always
image: nginx
container_name: nginx
ports:
- 80:80
- 433:433
volumes:
- /data/nginx/conf.d:/etc/nginx/conf.d
- /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- /data/nginx/log:/var/log/nginx
- /data/nginx/html:/usr/share/nginx/html
-
运行
docker-compose up
# 不同yml docker-compose -f docker-compose.yml -f production.yml up -d # 特定service docker-compose build web docker-compose up --no-deps -d web # 其他 docker-compse -h docker-compse ps docker-compose stop docker-compose down --volumes
K8S
kubernetes:容器编排解决方案,用来对容器化应用进行自动化部署、 扩缩和管理。
K8S组件
- Master组件:集群控制平台
- kube-apiserver:提供 Kubernetes API。Kubernetes管理工具:kubectl / kubernetes dashboard / kuboard
- etcd:支持一致性和高可用的名值对存储组件。存储Kubernetes集群的所有配置信息。
- kube-scheduler:监控所有新创建尚未分配到节点上的 Pod,并且自动为 Pod 选择合适的节点运行。
- kube-controller-manager:运行了所有的控制器
- Node 组件:运行在每一个节点上(包括 master 节点和 worker 节点),负责维护运行中的 Pod 并提供 Kubernetes 运行时环境。
- kubelet:运行在每一个集群节点上的代理程序,确保 Pod 中的容器处于运行状态。
- kube-proxy:网络代理程序。
- 容器引擎:docker、containerd
入门
Kubernetes 部署
Deployment 处于 master 节点上,通过发布 Deployment,master 节点会选择合适的 worker 节点创建 Container,Container 会被包含在 Pod里。
-
通过kubectl部署nginx Deployment
# 创建nginx-deployment.yaml apiVersion: apps/v1 #与k8s集群版本有关,使用 kubectl api-versions 即可查看当前集群支持的版本 kind: Deployment #该配置的类型,我们使用的是 Deployment metadata: #译名为元数据,即 Deployment 的一些基本属性和信息 name: nginx-deployment #Deployment 的名称 labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组 app: nginx #为该Deployment设置key为app,value为nginx的标签 spec: #这是关于该Deployment的描述,可以理解为你期待该Deployment在k8s中如何使用 replicas: 1 #使用该Deployment创建一个应用程序实例,用于应用程序的伸缩。 selector: #标签选择器,与上面的标签共同作用,目前不需要理解 matchLabels: #选择包含标签app:nginx的资源 app: nginx template: #这是选择或创建的Pod的模板 metadata: #Pod的元数据 labels: #Pod的标签,上面的selector即选择包含标签app:nginx的Pod app: nginx spec: #期望Pod实现的功能(即在pod中部署) containers: #生成container,与docker中的container是同一种 - name: nginx #container的名称 image: nginx:1.7.9 #使用镜像nginx:1.7.9创建container,该container默认80端口可访问
# 应用yaml文件 kubectl apply -f nginx-deployment.yaml # 查看 Deployment kubectl get deployments # 查看 Pod kubectl get pods
查看Pods/Nodes
Pod 容器组 k8s 集群上的最基本的单元,是一组容器(可包含一个或多个应用程序容器),以及共享存储(卷 Volumes)、IP 地址和有关如何运行容器的信息。
同一 Pod 中的不同 container 端口不能相互冲突。同一个Pod内的容器可以使用 localhost + 端口号互相访问。
在 k8s 上创建 Deployment 时,会在集群上创建包含容器的 Pod (而不是直接创建容器)。每个Pod都与运行它的 worker 节点(Node)绑定,并保持在那里直到终止或被删除。如果节点(Node)发生故障,则会在群集中的其他可用节点(Node)上运行相同的 Pod(从同样的镜像创建 Container,使用同样的配置,IP 地址不同,Pod 名字不同)
Node(节点)是 kubernetes 集群中的计算机,可以是虚拟机或物理机。
kubernetes master 会根据每个 Node(节点)上可用资源的情况,自动调度 Pod(容器组)到最佳的 Node(节点)上
每个 Kubernetes Node(节点)至少运行:
- Kubelet,负责 master 节点和 worker 节点之间通信的进程;管理 Pod(容器组)和 Pod(容器组)内运行的 Container(容器)。
- 容器运行环境(如Docker)负责下载镜像、创建和运行容器等。
# kubectl get 资源类型
#获取类型为Deployment的资源列表
kubectl get deployments
#获取类型为Pod的资源列表
kubectl get pods
#获取类型为Node的资源列表
kubectl get nodes
# 查看所有名称空间的 Deployment
kubectl get deployments -A
kubectl get deployments --all-namespaces
# 查看 kube-system 名称空间的 Deployment
kubectl get deployments -n kube-system
# kubectl describe 资源类型 资源名称
#查看名称为nginx-XXXXXX的Pod的信息
kubectl describe pod nginx-XXXXXX
#查看名称为nginx的Deployment的信息
kubectl describe deployment nginx
# kubectl logs Pod名称
#查看名称为nginx-pod-XXXXXXX的Pod内的容器打印的日志
#本案例中的 nginx-pod 没有输出日志,所以您看到的结果是空的
kubectl logs -f nginx-pod-XXXXXXX
# kubectl exec Pod名称 操作命令
# 在名称为nginx-pod-xxxxxx的Pod中运行bash
kubectl exec -it nginx-pod-xxxxxx /bin/bash
公布应用程序-service
Service是一个抽象层,通过 LabelSelector 选择了一组 Pod(容器组),把这些 Pod 的指定端口公布到到集群外部,并支持负载均衡和服务发现。
- 公布 Pod 的端口以使其可访问
- 在多个 Pod 间实现负载均衡
- 使用 Label 和 LabelSelector
# 创建nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service #Service 的名称
labels: #Service 自己的标签
app: nginx #为该 Service 设置 key 为 app,value 为 nginx 的标签
spec: #这是关于该 Service 的定义,描述了 Service 如何选择 Pod,如何被访问
selector: #标签选择器
app: nginx #选择包含标签 app:nginx 的 Pod
ports:
- name: nginx-port #端口的名字
protocol: TCP #协议类型 TCP/UDP
port: 80 #集群内的其他容器组可通过 80 端口访问 Service
nodePort: 32600 #通过任意节点的 32600 端口访问 Service
targetPort: 80 #将请求转发到匹配 Pod 的 80 端口
type: NodePort #Serive的类型,ClusterIP/NodePort/LoaderBalancer
kubectl apply -f nginx-service.yaml
kubectl get services -o wide
curl <任意节点的 IP>:32600
滚动更新Rolling Update
滚动更新允许以下操作:
- 将应用程序从准上线环境升级到生产环境(通过更新容器镜像)
- 回滚到以前的版本
- 持续集成和持续交付应用程序,无需停机
# 前提是将应用程序 Scale Up(扩容)为多个实例。
replicas: 4
image: nginx:1.8 #使用镜像nginx:1.8替换原来的nginx:1.7.9
kubectl apply -f nginx-deployment.yaml
# 执行命令,可观察到 pod 逐个被替换的过程
watch kubectl get pods -l app=nginx
进阶
架构
-
节点
-
节点信息(由节点上的 kubelet 收集)
kubectl get nodes -o wide kubectl describe node <your-node-name>
-
节点管理(组件Node Controller)
# 手动将节点标记为不可调度(unschedulable),阻止新的 Pod 被调度到该节点上,但是不影响任何已经在该节点上运行的 Pod。这在准备重启节点之前非常有用。 kubectl cordon $NODENAME
-
-
集群内的通信(从单master到k8s高可用)
- Cluster to Master
所有从集群访问 Master 节点的通信,都是针对 apiserver 的。apiserver 监听 HTTPS 端口(443)并配置授权方式。
-
Master to Cluster
- apiserver 访问集群中每个节点上的 kubelet 进程
- 使用 apiserver 的 proxy 功能,从 apiserver 访问集群中的任意节点、Pod、Service
操作k8s
-
k8s对象
-
namespace
# 查看集群中的名称空间列表 kubectl get namespaces --show-labels # 查看名称空间的概要信息 kubectl describe namespaces <name> # 直接使用命令创建删除名称空间:development 和 production kubectl create namespace <名称空间的名字> kubectl delete namespaces <名称空间的名字>
-
标签
容器
-
容器生命周期事件处理
Kubernetes 中支持容器的 postStart 和 preStop 处理程序(handler)。
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","nginx -s quit; while killall -0 nginx; do sleep 1; done"]
工作负载
-
Pod容器组
将多个容器运行于同一个容器组中是一种相对高级复杂的使用方法。只有在您的容器相互之间紧密耦合是,您才应该使用这种方式。例如:您可能有一个容器是 web server,用来将共享数据卷中的文件作为网站发布出去,同时您有另一个 “sidecar” 容器从远程抓取并更新这些文件。
-
Deployment控制器
用户应该始终使用控制器来创建 Pod,而不是直接创建 Pod,控制器可以提供如下特性:
- 水平扩展(运行 Pod 的多个副本)
- rollout(版本更新)
- self-healing(故障恢复)
MORE