CRI-O教程#

技术介绍#

CRI-O是一个轻量级的容器运行时,专为Kubernetes设计,实现了Kubernetes容器运行时接口(CRI)。它提供了一个与Kubernetes完全兼容的容器运行时环境,专注于简单性、安全性和性能。CRI-O使用OCI(Open Container Initiative)兼容的运行时,如runc,来运行容器。

CRI-O核心概念#

  • 容器:运行在隔离环境中的应用
  • 镜像:容器的只读模板
  • Pod:Kubernetes中的Pod概念,包含一个或多个容器
  • 运行时:执行容器的底层运行时,如runc
  • 存储:容器的存储管理
  • 网络:容器的网络配置

CRI-O架构#

  • 核心组件:CRI-O daemon、OCI运行时、镜像管理
  • API:Kubernetes CRI接口
  • 集成:与Kubernetes无缝集成
  • 插件系统:存储、网络、监控等插件

入门级使用#

安装CRI-O#

在不同操作系统上安装CRI-O:

# Ubuntu/Debian
# 添加CRI-O仓库
. /etc/os-release
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key | sudo apt-key add -

# 安装CRI-O
apt-get update
apt-get install cri-o cri-o-runc

# CentOS/RHEL
# 添加CRI-O仓库
yum-config-manager --add-repo=https://cbs.centos.org/repos/paas7-crio-311-candidate/x86_64/os/

# 安装CRI-O
yum install cri-o

# 启动CRI-O服务
systemctl start crio
systemctl enable crio

# 验证安装
crio --version
crictl version

基本CRI-O命令#

使用CRI-O的基本命令:

# 查看CRI-O版本
crio --version

# 查看crictl版本
crictl version

# 查看CRI-O状态
systemctl status crio

# 查看镜像
crictl images

# 拉取镜像
crictl pull docker.io/library/ubuntu:20.04

# 查看Pod
crictl pods

# 查看容器
crictl containers

# 运行容器
# 首先创建Pod sandbox
POD_ID=$(crictl runp pod-config.json)

# 然后在Pod中运行容器
CONTAINER_ID=$(crictl create $POD_ID container-config.json pod-config.json)
crictl start $CONTAINER_ID

# 停止容器
crictl stop $CONTAINER_ID
crictl rm $CONTAINER_ID

# 停止Pod sandbox
crictl stopp $POD_ID
crictl rmp $POD_ID

配置文件#

配置CRI-O:

# 查看CRI-O配置
cat /etc/crio/crio.conf

# 配置示例
# /etc/crio/crio.conf
[crio.runtime]
runtime_path = "/usr/bin/runc"
runtime_root = "/run/runc"
runtime_engine = "runc"
runtime_mode = "oci"

[crio.image]
default_transport = "docker://"

[crio.network]
network_dir = "/etc/cni/net.d"
plugin_dirs = ["/opt/cni/bin"]

# 重启CRI-O服务
systemctl restart crio

初级使用#

CRI-O镜像管理#

管理CRI-O镜像:

# 查看镜像
crictl images

# 拉取镜像
crictl pull docker.io/library/ubuntu:20.04

# 推送镜像
crictl push docker.io/library/ubuntu:20.04

# 删除镜像
crictl rmi docker.io/library/ubuntu:20.04

# 查看镜像详情
crictl inspecti docker.io/library/ubuntu:20.04

# 清理未使用的镜像
crictl rmi --prune

CRI-O容器管理#

管理CRI-O容器:

# 查看容器
crictl containers

# 创建容器
# 首先创建Pod sandbox配置
cat > pod-config.json <<EOF
{
  "metadata": {
    "name": "sandbox",
    "namespace": "default",
    "attempt": 1,
    "uid": "hdishd83djaidwnduwk28bcsb"
  },
  "log_directory": "/tmp",
  "linux": {}
}
EOF

# 创建容器配置
cat > container-config.json <<EOF
{
  "metadata": {
    "name": "container"
  },
  "image": {
    "image": "docker.io/library/ubuntu:20.04"
  },
  "command": ["/bin/bash", "-c", "echo hello world"],
  "linux": {}
}
EOF

# 运行Pod sandbox
POD_ID=$(crictl runp pod-config.json)

# 创建容器
CONTAINER_ID=$(crictl create $POD_ID container-config.json pod-config.json)

# 启动容器
crictl start $CONTAINER_ID

# 查看容器日志
crictl logs $CONTAINER_ID

# 进入容器
crictl exec -i -t $CONTAINER_ID /bin/bash

# 停止容器
crictl stop $CONTAINER_ID
crictl rm $CONTAINER_ID

# 停止Pod sandbox
crictl stopp $POD_ID
crictl rmp $POD_ID

CRI-O网络配置#

配置CRI-O网络:

# 查看网络配置
ls /etc/cni/net.d/

# 创建CNI网络配置
cat > /etc/cni/net.d/10-bridge.conf <<EOF
{
  "cniVersion": "0.3.1",
  "name": "bridge",
  "type": "bridge",
  "bridge": "cni0",
  "isGateway": true,
  "ipMasq": true,
  "ipam": {
    "type": "host-local",
    "subnet": "10.88.0.0/16",
    "routes": [
      {
        "dst": "0.0.0.0/0"
      }
    ]
  }
}
EOF

# 重启CRI-O服务
systemctl restart crio

# 测试网络
# 创建Pod和容器,然后测试网络连接

中级使用#

CRI-O运行时配置#

配置CRI-O运行时:

# 编辑CRI-O配置
vim /etc/crio/crio.conf

# 配置runc运行时
[crio.runtime]
runtime_path = "/usr/bin/runc"
runtime_root = "/run/runc"
runtime_engine = "runc"
runtime_mode = "oci"

# 配置gVisor运行时
# 安装gVisor
gcurl -fsSL https://gvisor.dev/archive/master/latest/x86_64/releases/runsc | sudo tee /usr/local/bin/runsc > /dev/null
sudo chmod +x /usr/local/bin/runsc

# 配置gVisor运行时
[crio.runtime.runtimes.runsc]
runtime_path = "/usr/local/bin/runsc"
runtime_type = "oci"
runtime_engine = ""
runtime_root = "/run/runsc"

# 重启CRI-O服务
systemctl restart crio

# 使用gVisor运行时
# 在容器配置中指定runtime_handler

CRI-O存储配置#

配置CRI-O存储:

# 编辑CRI-O配置
vim /etc/crio/crio.conf

# 配置存储
[crio.image]
default_transport = "docker://"
pause_image = "k8s.gcr.io/pause:3.2"
pause_command = "/pause"

[crio.runtime]
runtime_path = "/usr/bin/runc"
runtime_root = "/run/runc"
runtime_engine = "runc"
runtime_mode = "oci"

# 配置存储后端
[crio.storage]
storage_driver = "overlay"
storage_option = [
  "overlay2.override_kernel_check=true"
]

# 重启CRI-O服务
systemctl restart crio

CRI-O与Kubernetes集成#

将CRI-O与Kubernetes集成:

# 安装kubeadm、kubelet、kubectl
apt-get update
apt-get install -y kubelet kubeadm kubectl

# 配置kubelet使用CRI-O
cat > /etc/default/kubelet <<EOF
KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime-endpoint=unix:///var/run/crio/crio.sock
EOF

# 初始化Kubernetes集群
kubeadm init --pod-network-cidr=10.244.0.0/16

# 配置kubectl
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

# 安装网络插件
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

# 查看节点状态
kubectl get nodes

# 查看Pod状态
kubectl get pods --all-namespaces

中上级使用#

CRI-O性能优化#

优化CRI-O性能:

# 编辑CRI-O配置
vim /etc/crio/crio.conf

# 优化运行时
[crio.runtime]
runtime_path = "/usr/bin/runc"
runtime_root = "/run/runc"
runtime_engine = "runc"
runtime_mode = "oci"
runtimes = [
  "runc",
  "runsc"
]

# 优化存储
[crio.storage]
storage_driver = "overlay2"
storage_option = [
  "overlay2.override_kernel_check=true",
  "overlay2.size=10G"
]

# 优化网络
[crio.network]
network_dir = "/etc/cni/net.d"
plugin_dirs = ["/opt/cni/bin"]

# 重启CRI-O服务
systemctl restart crio

# 重启kubelet服务
systemctl restart kubelet

CRI-O安全配置#

配置CRI-O安全选项:

# 编辑CRI-O配置
vim /etc/crio/crio.conf

# 配置安全选项
[crio.runtime]
runtime_path = "/usr/bin/runc"
runtime_root = "/run/runc"
runtime_engine = "runc"
runtime_mode = "oci"

# 配置默认安全上下文
[crio.runtime.default]
security_context = {
  "namespace_options": {
    "network_namespace": "",
    "pid_namespace": "",
    "ipc_namespace": "",
    "mount_namespace": "",
    "user_namespace": ""
  },
  "capabilities": {
    "add": [],
    "drop": ["ALL"]
  },
  "selinux_options": {
    "user": "",
    "role": "",
    "type": "",
    "level": ""
  }
}

# 重启CRI-O服务
systemctl restart crio

CRI-O监控#

监控CRI-O:

# 启用CRI-O指标
# 编辑CRI-O配置
vim /etc/crio/crio.conf

# 启用指标
[crio.metrics]
enable_metrics = true
metrics_port = 9537

# 重启CRI-O服务
systemctl restart crio

# 使用Prometheus监控CRI-O
# 创建Prometheus配置
cat > prometheus.yml <<EOF
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'crio'
    static_configs:
      - targets: ['localhost:9537']
EOF

# 运行Prometheus
podman run -d --name prometheus \
  -p 9090:9090 \
  -v ./prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus

# 使用Grafana查看监控数据
podman run -d --name grafana \
  -p 3000:3000 \
  grafana/grafana

高级使用#

CRI-O集群管理#

管理CRI-O集群:

# 在多个节点上安装CRI-O
# 节点1
ssh node1 "apt install cri-o cri-o-runc"

# 节点2
ssh node2 "apt install cri-o cri-o-runc"

# 节点3
ssh node3 "apt install cri-o cri-o-runc"

# 配置Kubernetes集群
# 在主节点上初始化集群
kubeadm init --pod-network-cidr=10.244.0.0/16

# 在工作节点上加入集群
kubeadm join <master-ip>:6443 --token <token> --discovery-token-ca-cert-hash <hash>

# 查看集群状态
kubectl get nodes

# 部署应用
kubectl apply -f deployment.yaml

# 查看应用状态
kubectl get pods

CRI-O与Istio集成#

将CRI-O与Istio集成:

# 安装Istio
curl -L https://istio.io/downloadIstio | sh -
cd istio-*
export PATH=$PWD/bin:$PATH

# 部署Istio
istioctl install --set profile=demo -y

# 标记命名空间以启用Istio
kubectl label namespace default istio-injection=enabled

# 部署应用
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

# 查看应用状态
kubectl get pods

# 访问应用
kubectl get svc istio-ingressgateway -n istio-system

CRI-O安全审计#

进行CRI-O安全审计:

# 检查CRI-O配置
cat /etc/crio/crio.conf

# 检查容器安全上下文
crictl inspect $CONTAINER_ID | grep -A 20 security_context

# 使用Trivy扫描镜像漏洞
crictl pull docker.io/library/ubuntu:20.04
crictl inspecti docker.io/library/ubuntu:20.04 | grep -A 10 "RepoDigests"
# 使用Trivy扫描镜像
podman run --rm aquasec/trivy image docker.io/library/ubuntu:20.04

# 检查运行时安全
# 使用gVisor运行时
# 在容器配置中指定runtime_handler为runsc

# 检查网络安全
# 使用Cilium网络插件
kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/v1.9/install/kubernetes/quick-install.yaml

大师级使用#

CRI-O企业级部署#

企业级CRI-O部署:

# 配置高可用性
# 部署多个CRI-O节点

# 配置负载均衡
# 使用HAProxy负载均衡Kubernetes API服务器

# 配置存储
# 使用分布式存储作为容器存储后端

# 配置网络
# 使用Calico或Cilium作为Kubernetes网络插件

# 部署应用
# 使用Kubernetes部署应用
kubectl apply -f deployment.yaml

# 配置监控
# 使用Prometheus和Grafana监控CRI-O和Kubernetes

# 配置日志
# 使用ELK Stack收集和分析日志

# 配置安全
# 使用Pod Security Policies或Pod Security Standards
kubectl apply -f psp.yaml

CRI-O与Knative集成#

将CRI-O与Knative集成:

# 安装Knative
kubectl apply -f https://github.com/knative/serving/releases/download/v0.22.0/serving-crds.yaml
kubectl apply -f https://github.com/knative/serving/releases/download/v0.22.0/serving-core.yaml

# 安装Knative网络插件
kubectl apply -f https://github.com/knative/net-istio/releases/download/v0.22.0/net-istio.yaml

# 部署Serverless应用
cat > service.yaml <<EOF
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: hello-world
spec:
  template:
    spec:
      containers:
      - image: gcr.io/knative-samples/helloworld-go
        env:
        - name: TARGET
          value: "World"
EOF

kubectl apply -f service.yaml

# 查看应用状态
kubectl get ksvc

CRI-O性能调优#

调优CRI-O性能:

# 编辑CRI-O配置
vim /etc/crio/crio.conf

# 调优运行时
[crio.runtime]
runtime_path = "/usr/bin/runc"
runtime_root = "/run/runc"
runtime_engine = "runc"
runtime_mode = "oci"
runtime_request_timeout = "30s"
runtime_servers = [
  {
    "address": "/var/run/crio/crio.sock",
    "stream_address": "",
    "stream_port": "",
    "runtime": "runc",
    "runtime_root": "/run/runc",
    "runtime_path": "/usr/bin/runc",
    "runtime_engine": "",
    "runtime_mode": "oci",
    "extensions": [],
    "allowed_annotations": [],
    "allowed_devices": [],
    "allowed_untrusted_artifacts": [],
    "default_mounts": [],
    "no_pivot": false,
    "sandbox_image": "k8s.gcr.io/pause:3.2"
  }
]

# 调优存储
[crio.storage]
storage_driver = "overlay2"
storage_option = [
  "overlay2.override_kernel_check=true",
  "overlay2.size=10G",
  "overlay2.metacopy=on"
]

# 调优网络
[crio.network]
network_dir = "/etc/cni/net.d"
plugin_dirs = ["/opt/cni/bin"]

# 重启CRI-O服务
systemctl restart crio

# 重启kubelet服务
systemctl restart kubelet

实战案例#

案例一:部署微服务应用#

场景:部署一个基于Spring Boot的微服务应用。

解决方案:使用CRI-O和Kubernetes部署微服务应用。

实施步骤

  1. 构建镜像

    # 使用buildkit构建镜像
    buildctl build --frontend=dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=myapp:latest
    
    # 推送镜像到仓库
    crictl pull myapp:latest
  2. 创建Kubernetes部署

    # deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: myapp
      template:
        metadata:
          labels:
            app: myapp
        spec:
          containers:
          - name: myapp
            image: myapp:latest
            ports:
            - containerPort: 8080
  3. 部署应用

    kubectl apply -f deployment.yaml
    kubectl apply -f service.yaml
    
    # 查看应用状态
    kubectl get pods
    kubectl get svc

结果

  • 成功构建了Spring Boot应用的镜像
  • 部署了高可用的微服务应用
  • 应用可以通过Service访问

案例二:CRI-O安全加固#

场景:加固CRI-O容器安全。

解决方案:配置CRI-O安全选项。

实施步骤

  1. 配置CRI-O安全选项
    # 编辑/etc/crio/crio.conf
    [crio.runtime]

runtime_path = “/usr/bin/runc” runtime_root = “/run/runc” runtime_engine = “runc” runtime_mode = “oci”

配置默认安全上下文#

[crio.runtime.default] security_context = { “namespace_options”: { “network_namespace”: “”, “pid_namespace”: “”, “ipc_namespace”: “”, “mount_namespace”: “”, “user_namespace”: "" }, “capabilities”: { “add”: [], “drop”: [“ALL”] }, “selinux_options”: { “user”: “”, “role”: “”, “type”: “”, “level”: "" } }


2. **使用gVisor运行时**:
```bash
# 安装gVisor
curl -fsSL https://gvisor.dev/archive/master/latest/x86_64/releases/runsc | sudo tee /usr/local/bin/runsc > /dev/null
sudo chmod +x /usr/local/bin/runsc

# 配置gVisor运行时
[crio.runtime.runtimes.runsc]
runtime_path = "/usr/local/bin/runsc"
runtime_type = "oci"
runtime_engine = ""
runtime_root = "/run/runsc"
  1. 重启CRI-O服务
    systemctl restart crio

结果

  • 成功配置了CRI-O安全选项
  • 使用了gVisor运行时提高安全性
  • 容器运行在更安全的环境中

案例三:CRI-O性能优化#

场景:优化CRI-O性能。

解决方案:配置CRI-O性能选项。

实施步骤

  1. 配置CRI-O性能选项
    # 编辑/etc/crio/crio.conf
    [crio.runtime]

runtime_path = “/usr/bin/runc” runtime_root = “/run/runc” runtime_engine = “runc” runtime_mode = “oci” runtime_request_timeout = “30s”

配置存储#

[crio.storage] storage_driver = “overlay2” storage_option = [ “overlay2.override_kernel_check=true”, “overlay2.size=10G”, “overlay2.metacopy=on” ]

配置网络#

[crio.network] network_dir = “/etc/cni/net.d” plugin_dirs = ["/opt/cni/bin"]


2. **使用更快的存储后端**:
```bash
# 使用zfs作为存储后端
apt install zfsutils-linux

# 配置zfs存储后端
[crio.storage]
storage_driver = "zfs"
storage_option = [
  "zfs.fsname=zpool/crio"
]
  1. 重启CRI-O服务
    systemctl restart crio
    systemctl restart kubelet

结果

  • 成功优化了CRI-O性能
  • 提高了容器启动速度和运行效率
  • 减少了资源使用

总结#

CRI-O是一种轻量级、安全、高性能的容器运行时,专为Kubernetes设计。通过本教程的学习,您已经掌握了从入门到大师级的CRI-O使用技术。

主要技术回顾#

  • 基础操作:CRI-O的基本命令和操作
  • 镜像管理:拉取、推送、构建镜像
  • 容器管理:创建、启动、停止容器
  • Pod管理:创建和管理Pod sandbox
  • 存储管理:配置存储后端
  • 网络管理:配置CNI网络
  • 运行时管理:配置不同的容器运行时
  • 高级功能:集群管理、监控、安全加固
  • 企业级应用:高可用性、负载均衡、性能优化

最佳实践#

  1. 使用最新版本:定期更新CRI-O版本,获取最新的安全补丁和功能
  2. 配置合理:根据实际需求配置CRI-O,避免过度配置
  3. 安全加固:使用非特权容器,配置适当的capabilities,使用gVisor等安全运行时
  4. 性能优化:根据硬件环境优化CRI-O配置,提高性能
  5. 监控容器:使用Prometheus等工具监控CRI-O状态
  6. 自动化部署:与CI/CD集成,实现自动化构建、测试和部署
  7. 备份策略:制定容器数据备份策略,确保数据安全
  8. 灾难恢复:建立容器环境的灾难恢复计划,应对突发情况

注意事项#

  1. 版本兼容性:确保CRI-O版本与Kubernetes版本兼容
  2. 资源管理:合理配置容器资源限制,避免资源争用
  3. 网络配置:合理配置网络,确保容器间通信安全
  4. 存储管理:定期清理未使用的镜像、容器和内容,释放存储空间
  5. 安全审计:定期进行CRI-O安全审计,发现和修复安全问题
  6. 故障排查:熟悉CRI-O日志和监控,快速排查问题

通过合理学习和使用CRI-O,您可以获得更高效、更安全的容器运行环境。CRI-O作为专为Kubernetes设计的容器运行时,已经被广泛应用于生产环境,掌握CRI-O技术将为您的职业发展带来更多机会。