containerd中文翻译系列(十九)cri插件

cri插件包含的内容比较多,阅读之前请深呼吸三次、三次、三次。

CRI 插件的架构

本小节介绍了 containerdcri 插件的架构。

该插件是 Kubernetes 容器运行时接口(CRI) 的实现。Containerd与Kubelet在同一个节点上运行。containerd内部的cri插件处理来自Kubelet的所有CRI服务请求,并使用containerd内部机制来管理容器和容器映像。

cri 插件使用 containerd 管理整个容器生命周期和所有容器镜像。如下所示,cri\通过 CNI(另一个 CNCF 项目)管理 pod 网络。

architecture.png

让我们以 Kubelet 创建单容器 pod 为例,演示 cri 插件是如何工作的:

  • Kubelet 通过 CRI 运行时服务 API 调用 cri 插件来创建 pod;
  • cri 创建 pod 的网络命名空间,然后使用 CNI 对其进行配置;
  • cri 使用 containerd 内部创建并启动一个特殊的暂停容器(沙盒容器),并将该容器置于 pod 的 cgroups 和命名空间内(为简洁起见,省略步骤)
  • 如果节点上没有镜像,cri会进一步使用containerd拉取镜像;
  • 然后,Kubelet 通过 CRI 运行时服务 API 调用 cri ,使用拉取的容器镜像在 pod 内创建并启动应用容器;
  • 最后,"cri "会使用内部containerd 来创建应用容器,将其放入 pod 的 cgroups 和命名空间中,然后启动 pod 的新应用容器。
    完成这些步骤后,一个 pod 及其相应的应用容器就创建完成并开始运行了。

CRI 插件配置指南

这一章节介绍 CRI 插件配置。
CRI 插件配置是 containerd 配置(默认
路径: /etc/containerd/config.toml`)。

了解有关 containerd 配置的更多信息。,请参阅 here

请注意,[plugins. "io.containerd.grpc.v1.cri"] 部分是 CRI 特有的、其他 containerd 客户端(如 ctrnerdctl 和 Docker/Moby)无法识别。

基本配置

cgroup 驱动程序

容器 d 和 Kubernetes 默认使用传统的 cgroupfs 驱动程序来管理 cgroup、
建议在基于 systemd 的主机上使用 systemd 驱动程序,以符合
cgroups 的"单写入器 "规则。

要配置 containerd 以使用 systemd 驱动程序,请在 /etc/containerd/config.toml中设置以下选项:

version = 2
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]SystemdCgroup = true

除 containerd 外,还必须配置 KubeletConfiguration 以使用 “systemd” cgroup 驱动程序。
KubeletConfiguration" 通常位于 /var/lib/kubelet/config.yaml:

kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: "systemd"

kubeadm 用户还应参阅 kubeadm 文档。

注意:Kubernetes v1.28 支持自动检测 cgroup 驱动程序,
作为一项 alpha 功能。启用 KubeletCgroupDriverFromCRI kubelet 功能后,kubelet 会自动从 CRI运行时检测到 cgroup 驱动程序,因此不需要上述的 KubeletConfiguration 配置步骤。
在确定 cgroup 驱动程序时,containerd 会使用基于 runc 的运行时中的 SystemdCgroup 设置。
从默认运行时类开始。如果没有配置基于 runc 的运行时类,containerd
则依赖于基于确定 systemd 是否正在运行的自动检测。
请注意,所有基于 runc 的运行时类都应配置为具有
相同的 SystemdCgroup 设置,以避免意外行为。
containerd v2.0 及更高版本中支持为 kubelet 自动配置cgroup驱动程序的功能。

快照程序

默认快照器设置为 overlayfs(类似于 Docker 的 overlay2 存储驱动程序):

version = 2
[plugins."io.containerd.grpc.v1.cri".containerd]snapshotter = "overlayfs"

有关其他支持的快照器,请参阅 此处。

运行时类

下面的示例将自定义运行时注册到 containerd 中:

version = 2
[plugins."io.containerd.grpc.v1.cri".containerd]default_runtime_name = "crun"[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]# crun: https://github.com/containers/crun[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun]runtime_type = "io.containerd.runc.v2"[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun.options]BinaryName = "/usr/local/bin/crun"# gVisor: https://gvisor.dev/[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.gvisor]runtime_type = "io.containerd.runsc.v1"# Kata Containers: https://katacontainers.io/[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata]runtime_type = "io.containerd.kata.v2"

此外,您还必须通过集群管理员角色将以下 RuntimeClass 资源安装到集群中:

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:name: crun
handler: crun
---
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:name: gvisor
handler: gvisor
---
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:name: kata
handler: kata

要将运行时类应用到 pod,请设置 .spec.runtimeClassName:

apiVersion: v1
kind: Pod
spec:runtimeClassName: crun

另请参阅 Kubernetes 文档。

完整配置

各配置项的说明和默认值如下:

# Use config version 2 to enable new configuration fields.
# Config file is parsed as version 1 by default.
# Version 2 uses long plugin names, i.e. "io.containerd.grpc.v1.cri" vs "cri".
version = 2# The 'plugins."io.containerd.grpc.v1.cri"' table contains all of the server options.
[plugins."io.containerd.grpc.v1.cri"]# disable_tcp_service disables serving CRI on the TCP server.# Note that a TCP server is enabled for containerd if TCPAddress is set in section [grpc].disable_tcp_service = true# stream_server_address is the ip address streaming server is listening on.stream_server_address = "127.0.0.1"# stream_server_port is the port streaming server is listening on.stream_server_port = "0"# stream_idle_timeout is the maximum time a streaming connection can be# idle before the connection is automatically closed.# The string is in the golang duration format, see:#   https://golang.org/pkg/time/#ParseDurationstream_idle_timeout = "4h"# enable_selinux indicates to enable the selinux support.enable_selinux = false# selinux_category_range allows the upper bound on the category range to be set.# if not specified or set to 0, defaults to 1024 from the selinux package.selinux_category_range = 1024# sandbox_image is the image used by sandbox container.sandbox_image = "registry.k8s.io/pause:3.9"# stats_collect_period is the period (in seconds) of snapshots stats collection.stats_collect_period = 10# enable_tls_streaming enables the TLS streaming support.# It generates a self-sign certificate unless the following x509_key_pair_streaming are both set.enable_tls_streaming = false# tolerate_missing_hugetlb_controller if set to false will error out on create/update# container requests with huge page limits if the cgroup controller for hugepages is not present.# This helps with supporting Kubernetes <=1.18 out of the box. (default is `true`)tolerate_missing_hugetlb_controller = true# ignore_image_defined_volumes ignores volumes defined by the image. Useful for better resource# isolation, security and early detection of issues in the mount configuration when using# ReadOnlyRootFilesystem since containers won't silently mount a temporary volume.ignore_image_defined_volumes = false# netns_mounts_under_state_dir places all mounts for network namespaces under StateDir/netns# instead of being placed under the hardcoded directory /var/run/netns. Changing this setting# requires that all containers are deleted.netns_mounts_under_state_dir = false# 'plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming' contains a x509 valid key pair to stream with tls.[plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]# tls_cert_file is the filepath to the certificate paired with the "tls_key_file"tls_cert_file = ""# tls_key_file is the filepath to the private key paired with the "tls_cert_file"tls_key_file = ""# max_container_log_line_size is the maximum log line size in bytes for a container.# Log line longer than the limit will be split into multiple lines. -1 means no# limit.max_container_log_line_size = 16384# disable_cgroup indicates to disable the cgroup support.# This is useful when the daemon does not have permission to access cgroup.disable_cgroup = false# disable_apparmor indicates to disable the apparmor support.# This is useful when the daemon does not have permission to access apparmor.disable_apparmor = false# restrict_oom_score_adj indicates to limit the lower bound of OOMScoreAdj to# the containerd's current OOMScoreAdj.# This is useful when the containerd does not have permission to decrease OOMScoreAdj.restrict_oom_score_adj = false# max_concurrent_downloads restricts the number of concurrent downloads for each image.max_concurrent_downloads = 3# disable_proc_mount disables Kubernetes ProcMount support. This MUST be set to `true`# when using containerd with Kubernetes <=1.11.disable_proc_mount = false# unset_seccomp_profile is the seccomp profile containerd/cri will use if the seccomp# profile requested over CRI is unset (or nil) for a pod/container (otherwise if this field is not set the# default unset profile will map to `unconfined`)# Note: The default unset seccomp profile should not be confused with the seccomp profile# used in CRI when the runtime default seccomp profile is requested. In the later case, the# default is set by the following code (https://github.com/containerd/containerd/blob/main/contrib/seccomp/seccomp_default.go).# To summarize, there are two different seccomp defaults, the unset default used when the CRI request is# set to nil or `unconfined`, and the default used when the runtime default seccomp profile is requested.unset_seccomp_profile = ""# enable_unprivileged_ports configures net.ipv4.ip_unprivileged_port_start=0# for all containers which are not using host network# and if it is not overwritten by PodSandboxConfig# Note that currently default is set to disabled but target change it in future, see:#   [k8s discussion](https://github.com/kubernetes/kubernetes/issues/102612)enable_unprivileged_ports = false# enable_unprivileged_icmp configures net.ipv4.ping_group_range="0 2147483647"# for all containers which are not using host network, are not running in user namespace# and if it is not overwritten by PodSandboxConfig# Note that currently default is set to disabled but target change it in future together with enable_unprivileged_portsenable_unprivileged_icmp = false# enable_cdi enables support of the Container Device Interface (CDI)# For more details about CDI and the syntax of CDI Spec files please refer to# https://tags.cncf.io/container-device-interface.# TODO: Deprecate this option when either Dynamic Resource Allocation(DRA)# or CDI support for the Device Plugins are graduated to GA.# `Dynamic Resource Allocation` KEP:# https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation# `Add CDI devices to device plugin API` KEP:# https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/4009-add-cdi-devices-to-device-plugin-apienable_cdi = true# cdi_spec_dirs is the list of directories to scan for CDI spec files# For more details about CDI configuration please refer to# https://tags.cncf.io/container-device-interface#containerd-configurationcdi_spec_dirs = ["/etc/cdi", "/var/run/cdi"]# drain_exec_sync_io_timeout is the maximum duration to wait for ExecSync API'# IO EOF event after exec init process exits. A zero value means there is no# timeout.## The string is in the golang duration format, see:#    https://golang.org/pkg/time/#ParseDuration## For example, the value can be '5h', '2h30m', '10s'.drain_exec_sync_io_timeout = "0s"# 'plugins."io.containerd.grpc.v1.cri".containerd' contains config related to containerd[plugins."io.containerd.grpc.v1.cri".containerd]# snapshotter is the default snapshotter used by containerd# for all runtimes, if not overridden by an experimental runtime's snapshotter config.snapshotter = "overlayfs"# no_pivot disables pivot-root (linux only), required when running a container in a RamDisk with runc.# This only works for runtime type "io.containerd.runtime.v1.linux".no_pivot = false# disable_snapshot_annotations disables to pass additional annotations (image# related information) to snapshotters. These annotations are required by# stargz snapshotter (https://github.com/containerd/stargz-snapshotter)# changed to default true with https://github.com/containerd/containerd/pull/4665 and subsequent service refreshes.disable_snapshot_annotations = true# discard_unpacked_layers allows GC to remove layers from the content store after# successfully unpacking these layers to the snapshotter.discard_unpacked_layers = false# default_runtime_name is the default runtime name to use.default_runtime_name = "runc"# ignore_blockio_not_enabled_errors disables blockio related# errors when blockio support has not been enabled. By default,# trying to set the blockio class of a container via annotations# produces an error if blockio hasn't been enabled.  This config# option practically enables a "soft" mode for blockio where these# errors are ignored and the container gets no blockio class.ignore_blockio_not_enabled_errors = false# ignore_rdt_not_enabled_errors disables RDT related errors when RDT# support has not been enabled. Intel RDT is a technology for cache and# memory bandwidth management. By default, trying to set the RDT class of# a container via annotations produces an error if RDT hasn't been enabled.# This config option practically enables a "soft" mode for RDT where these# errors are ignored and the container gets no RDT class.ignore_rdt_not_enabled_errors = false# 'plugins."io.containerd.grpc.v1.cri".containerd.default_runtime' is the runtime to use in containerd.# DEPRECATED: use `default_runtime_name` and `plugins."io.containerd.grpc.v1.cri".containerd.runtimes` instead.[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]# 'plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime' is a runtime to run untrusted workloads on it.# DEPRECATED: use `untrusted` runtime in `plugins."io.containerd.grpc.v1.cri".containerd.runtimes` instead.[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]# 'plugins."io.containerd.grpc.v1.cri".containerd.runtimes' is a map from CRI RuntimeHandler strings, which specify types# of runtime configurations, to the matching configurations.# In this example, 'runc' is the RuntimeHandler string to match.[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]# runtime_type is the runtime type to use in containerd.# The default value is "io.containerd.runc.v2" since containerd 1.4.# The default value was "io.containerd.runc.v1" in containerd 1.3, "io.containerd.runtime.v1.linux" in prior releases.runtime_type = "io.containerd.runc.v2"# pod_annotations is a list of pod annotations passed to both pod# sandbox as well as container OCI annotations. Pod_annotations also# supports golang path match pattern - https://golang.org/pkg/path/#Match.# e.g. ["runc.com.*"], ["*.runc.com"], ["runc.com/*"].## For the naming convention of annotation keys, please reference:# * Kubernetes: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/#syntax-and-character-set# * OCI: https://github.com/opencontainers/image-spec/blob/main/annotations.mdpod_annotations = []# container_annotations is a list of container annotations passed through to the OCI config of the containers.# Container annotations in CRI are usually generated by other Kubernetes node components (i.e., not users).# Currently, only device plugins populate the annotations.container_annotations = []# privileged_without_host_devices allows overloading the default behaviour of passing host# devices through to privileged containers. This is useful when using a runtime where it does# not make sense to pass host devices to the container when privileged. Defaults to false -# i.e pass host devices through to privileged containers.privileged_without_host_devices = false# privileged_without_host_devices_all_devices_allowed allows the allowlisting of all devices when# privileged_without_host_devices is enabled.# In plain privileged mode all host device nodes are added to the container's spec and all devices# are put in the container's device allowlist. This flags is for the modification of the privileged_without_host_devices# option so that even when no host devices are implicitly added to the container, all devices allowlisting is still enabled.# Requires privileged_without_host_devices to be enabled. Defaults to false.privileged_without_host_devices_all_devices_allowed = false# base_runtime_spec is a file path to a JSON file with the OCI spec that will be used as the base spec that all# container's are created from.# Use containerd's `ctr oci spec > /etc/containerd/cri-base.json` to output initial spec file.# Spec files are loaded at launch, so containerd daemon must be restarted on any changes to refresh default specs.# Still running containers and restarted containers will still be using the original spec from which that container was created.base_runtime_spec = ""# conf_dir is the directory in which the admin places a CNI conf.# this allows a different CNI conf for the network stack when a different runtime is being used.cni_conf_dir = "/etc/cni/net.d"# cni_max_conf_num specifies the maximum number of CNI plugin config files to# load from the CNI config directory. By default, only 1 CNI plugin config# file will be loaded. If you want to load multiple CNI plugin config files# set max_conf_num to the number desired. Setting cni_max_config_num to 0 is# interpreted as no limit is desired and will result in all CNI plugin# config files being loaded from the CNI config directory.cni_max_conf_num = 1# snapshotter overrides the global default snapshotter to a runtime specific value.# Please be aware that overriding the default snapshotter on a runtime basis is currently an experimental feature.# See https://github.com/containerd/containerd/issues/6657 for context.snapshotter = ""# treat_ro_mounts_as_rro ("Enabled"|"IfPossible"|"Disabled")# treats read-only mounts as recursive read-only mounts.# An empty string means "IfPossible".# "Enabled" requires Linux kernel v5.12 or later.# Introduced in containerd v2.0.# This configuration does not apply to non-volume mounts such as "/sys/fs/cgroup".treat_ro_mounts_as_rro = ""# 'plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options' is options specific to# "io.containerd.runc.v1" and "io.containerd.runc.v2". Its corresponding options type is:#   https://github.com/containerd/containerd/blob/v1.3.2/runtime/v2/runc/options/oci.pb.go#L26 .[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]# NoPivotRoot disables pivot root when creating a container.NoPivotRoot = false# NoNewKeyring disables new keyring for the container.NoNewKeyring = false# ShimCgroup places the shim in a cgroup.ShimCgroup = ""# IoUid sets the I/O's pipes uid.IoUid = 0# IoGid sets the I/O's pipes gid.IoGid = 0# BinaryName is the binary name of the runc binary.BinaryName = ""# Root is the runc root directory.Root = ""# SystemdCgroup enables systemd cgroups.SystemdCgroup = false# CriuImagePath is the criu image pathCriuImagePath = ""# CriuWorkPath is the criu work path.CriuWorkPath = ""# 'plugins."io.containerd.grpc.v1.cri".cni' contains config related to cni[plugins."io.containerd.grpc.v1.cri".cni]# bin_dir is the directory in which the binaries for the plugin is kept.bin_dir = "/opt/cni/bin"# conf_dir is the directory in which the admin places a CNI conf.conf_dir = "/etc/cni/net.d"# max_conf_num specifies the maximum number of CNI plugin config files to# load from the CNI config directory. By default, only 1 CNI plugin config# file will be loaded. If you want to load multiple CNI plugin config files# set max_conf_num to the number desired. Setting max_config_num to 0 is# interpreted as no limit is desired and will result in all CNI plugin# config files being loaded from the CNI config directory.max_conf_num = 1# conf_template is the file path of golang template used to generate# cni config.# If this is set, containerd will generate a cni config file from the# template. Otherwise, containerd will wait for the system admin or cni# daemon to drop the config file into the conf_dir.# See the "CNI Config Template" section for more details.conf_template = ""# ip_pref specifies the strategy to use when selecting the main IP address for a pod.# options include:# * ipv4, "" - (default) select the first ipv4 address# * ipv6 - select the first ipv6 address# * cni - use the order returned by the CNI plugins, returning the first IP address from the resultsip_pref = "ipv4"# 'plugins."io.containerd.grpc.v1.cri".image_decryption' contains config related# to handling decryption of encrypted container images.[plugins."io.containerd.grpc.v1.cri".image_decryption]# key_model defines the name of the key model used for how the cri obtains# keys used for decryption of encrypted container images.# The [decryption document](https://github.com/containerd/containerd/blob/main/docs/cri/decryption.md)# contains additional information about the key models available.## Set of available string options: {"", "node"}# Omission of this field defaults to the empty string "", which indicates no key model,# disabling image decryption.## In order to use the decryption feature, additional configurations must be made.# The [decryption document](https://github.com/containerd/containerd/blob/main/docs/cri/decryption.md)# provides information of how to set up stream processors and the containerd imgcrypt decoder# with the appropriate key models.## Additional information:# * Stream processors: https://github.com/containerd/containerd/blob/main/docs/stream_processors.md# * Containerd imgcrypt: https://github.com/containerd/imgcryptkey_model = "node"# 'plugins."io.containerd.grpc.v1.cri".registry' contains config related to# the registry[plugins."io.containerd.grpc.v1.cri".registry]# config_path specifies a directory to look for the registry hosts configuration.## The cri plugin will look for and use config_path/host-namespace/hosts.toml#   configs if present OR load certificate files as laid out in the Docker/Moby#   specific layout https://docs.docker.com/engine/security/certificates/## If config_path is not provided defaults are used.## *** registry.configs and registry.mirrors that were a part of containerd 1.4# are now DEPRECATED and will only be used if the config_path is not specified.config_path = ""

注册表配置

下面是一个默认注册表主机配置的简单示例。设置
在 containerd 的 config.toml 中设置 config_path = "/etc/containerd/certs.d"
在配置路径下创建一个目录树,其中包括 docker.io 作为要配置的主机命名空间的目录。然后在docker.io目录中添加一个hosts.toml文件。
文件来配置主机命名空间。文件应该是这样的:

$ tree /etc/containerd/certs.d
/etc/containerd/certs.d
└── docker.io└── hosts.toml$ cat /etc/containerd/certs.d/docker.io/hosts.toml
server = "https://docker.io"[host."https://registry-1.docker.io"]capabilities = ["pull", "resolve"]

指定自定义证书:

$ cat /etc/containerd/certs.d/192.168.12.34:5000/hosts.toml
server = "https://192.168.12.34:5000"[host."https://192.168.12.34:5000"]ca = "/path/to/ca.crt"

更多信息请参见 docs/hosts.md

不受信任的工作负载

运行不受信任工作负载的推荐方法是使用 Kubernetes 1.12引入的
运行时类 api选择plugin."io.containerd.grpc.v1.cri.containerd.runtimes" 中配置为运行不信任工作负载的 RuntimeHandlers。

但是,如果使用传统的 io.kubernetes.cri.untrusted-workloadpod 注解
来请求使用不受信任工作负载的运行时运行 pod,那么 RuntimeHandler
必须首先定义plugins. "io.containerd.grpc.v1.cri.containerd.runtrusted"
当注解 io.kubernetes.cri.untrusted-workload 设置为 true 时,untrusted运行时将被使用。请参阅
使用kata容器创建不受信任的 pod。

CNI 配置模板

理想情况下,cni 配置应由系统管理员或 cni 守护进程(如 calico、weaveworks 等)放置。
不过,这对没有 cni 守护进程来放置 cni 配置的情况很有用。

cni 配置模板使用 golang
template格式。目前支持的
值是

  • .PodCIDR 是分配给节点的第一个 CIDR 的字符串。
  • .PodCIDRRanges 是分配给节点的所有 CIDR 的字符串数组。它
    通常用于
    dualstack支持。
  • .Routes 是一个包含所有所需路由的字符串数组。它通常用于
    通常用于支持双协议栈或单协议栈,但 IPv4 或 IPv6 则在运行时决定。

golang 模板动作](https://golang.org/pkg/text/template/#hdr-Actions)
可用于渲染 cni 配置。例如,您可以使用以下
模板在 CNI 配置中添加双协议栈的 CIDR 和路由:

"ipam": {"type": "host-local","ranges": [{{range $i, $range := .PodCIDRRanges}}{{if $i}}, {{end}}[{"subnet": "{{$range}}"}]{{end}}],"routes": [{{range $i, $route := .Routes}}{{if $i}}, {{end}}{"dst": "{{$route}}"}{{end}}]
}

过时

CRI 插件的配置选项遵循 Kubernetes Deprecation
面向管理员的 CLI 组件 "政策。

总之,当一个配置选项被宣布弃用时:

  • 在 6 个月或 1 个版本(以时间较长者为准)内保持其功能;
  • 使用时发出警告。

配置镜像解密

本小节介绍为 containerd 配置加密容器镜像解密的方法,以便与 cri 插件一起使用。

加密容器镜像

加密容器镜像是包含加密 blob 的 OCI 镜像。这些加密镜像可以通过使用 containerd/imgcrypt project 创建。要解密这些镜像,"containerd "运行时会使用从 "cri "传递过来的信息,如密钥、选项和加密元数据。

"节点"密钥模型

加密根据与密钥相关联的模型将信任与实体联系起来。我们称之为密钥模型。当我们想把密钥的信任度与集群中的节点联系起来时,就是这样一种用例。在这种情况下,我们称之为 "节点 "或 "主机 "密钥模型。未来的工作将包括更多的密钥模型,以促进其他信任关联(即多租户)。

"节点 "密钥模型 使用案例

在这种模式下,加密与工作节点绑定。这里的用例围绕着镜像只能在受信任的主机上解密这一想法展开。使用这种模式,各种基于节点的技术都有助于引导对工作节点的信任并执行安全密钥分发(即 TPM、主机认证、安全/测量引导)。在这种情况下,运行时能够获取必要的解密密钥。使用 imgcrypt 中的 [--decryption-keys-path 标志就是一个例子。

为 "节点 "密钥模型配置镜像解密

这是自 containerd v1.5 以来的默认模型。

对于 containerd v1.4,您需要将以下配置添加到 /etc/containerd/config.toml,并手动重启 containerd 服务。

version = 2[plugins."io.containerd.grpc.v1.cri".image_decryption]key_model = "node"[stream_processors][stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]returns = "application/vnd.oci.image.layer.v1.tar+gzip"path = "ctd-decoder"args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]env= ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"][stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]returns = "application/vnd.oci.image.layer.v1.tar"path = "ctd-decoder"args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]env= ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]

在本例中,容器图像解密被设置为使用 "节点 "密钥模型。
此外,解密 stream_processors的配置与 containerd/imgcrypt project 中指定的一样,并配置了附加字段 --decryption-keys-path,以指定解密密钥在节点本地的位置。

$OCICRYPT_KEYPROVIDER_CONFIG` 环境变量用于 ocicrypt keyprovider protocol

配置镜像注册表

本小节介绍为 containerd 配置镜像注册表的方法,以便与 cri 插件一起使用。

NOTE: 本文档中之前描述的 registry.mirrors 和 registry.configs
已被删除。如 the cri config 所述,现在应使用以下配置

[plugins."io.containerd.grpc.v1.cri".registry]config_path = "/etc/containerd/certs.d"

配置注册表凭据

NOTE: registry.configs.*.auth 已过时,还没有除了在主机
配置文件中存储未加密的secret的相应方法。在
有合适的secret管理替代插件出现后才会删除它。
在 1.x 版本中,包括 1.6 LTS 版本中仍会支持。

要为特定注册表配置证书,请创建/修改
/etc/containerd/config.toml":

# explicitly use v2 config format
version = 2# The registry host has to be a domain name or IP. Port number is also
# needed if the default HTTPS or HTTP port is not used.
[plugins."io.containerd.grpc.v1.cri".registry.configs."gcr.io".auth]username = ""password = ""auth = ""identitytoken = ""

每个字段的含义与.docker/config.json中的相应字段相同。

请注意,CRI 传递的 auth 配置优先于此配置。
该配置中的注册凭据只有在 auth 配置未由 Kubernetes 通过 CRI 指定时,才会使用此配置中的注册凭据。

修改此配置后,需要重新启动 containerd 服务。

配置注册表凭据示例 - 使用服务账户密钥身份验证的 GCR

如果尚未设置 Google Container Registry (GCR),则需要执行以下步骤:

  • 创建谷歌云平台(GCP)账户和项目(如果尚未创建)(请参阅 GCP 入门
  • 为您的项目启用 GCR(请参阅 Container Registry 快速入门
  • 为验证 GCR:创建 服务账户和 JSON 密钥
  • 需要从 GCP 控制台将 JSON 密钥文件下载到系统中。
  • 用于访问 GCR 存储: 向 GCR 存储桶添加具有存储管理访问权限的服务账户(请参阅 授予权限)。

有关上述步骤的详细信息,请参阅 推送和提取镜像。

注意:JSON 密钥文件是一个多行文件,将其内容用作文件外的密钥会很麻烦。因此值得生成该文件的单行格式输出。一种方法是使用 jq 工具,如下所示: jq -c . key.json

在将 GCR 挂接到 containerd 之前,最好先从终端确认自己可以通过 GCR 进行身份验证并访问存储。这可以通过登录 GCR 和向其推送映像,即可验证这一点:

docker login -u _json_key -p "$(cat key.json)" gcr.iodocker pull busyboxdocker tag busybox gcr.io/your-gcp-project-id/busyboxdocker push gcr.io/your-gcp-project-id/busyboxdocker logout gcr.io

既然知道可以从终端访问 GCR,现在就该试试 containerd 了。

编辑 containerd 配置(默认位置为 /etc/containerd/config.toml)
以添加用于gcr.io域镜像拉取的 JSON 密钥
请求:

version = 2[plugins."io.containerd.grpc.v1.cri".registry][plugins."io.containerd.grpc.v1.cri".registry.mirrors][plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]endpoint = ["https://registry-1.docker.io"][plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]endpoint = ["https://gcr.io"][plugins."io.containerd.grpc.v1.cri".registry.configs][plugins."io.containerd.grpc.v1.cri".registry.configs."gcr.io".auth]username = "_json_key"password = 'paste output from jq'

注意:_json_keyusername 表示将使用 JSON 密钥验证。

重启containerd:

service containerd restart

使用 crictl 从 GCR 中提取图像:

$ sudo crictl pull gcr.io/your-gcp-project-id/busyboxDEBU[0000] get image connection
DEBU[0000] connect using endpoint 'unix:///run/containerd/containerd.sock' with '3s' timeout
DEBU[0000] connected successfully using endpoint: unix:///run/containerd/containerd.sock
DEBU[0000] PullImageRequest: &PullImageRequest{Image:&ImageSpec{Image:gcr.io/your-gcr-instance-id/busybox,},Auth:nil,SandboxConfig:nil,}
DEBU[0001] PullImageResponse: &PullImageResponse{ImageRef:sha256:78096d0a54788961ca68393e5f8038704b97d8af374249dc5c8faec1b8045e42,}
Image is up to date for sha256:78096d0a54788961ca68393e5f8038704b97d8af374249dc5c8faec1b8045e42

注意:本文档中使用的配置语法是自 containerd 1.3 以来推荐使用的第 2 版。有关以前的配置格式,请参考 https://github.com/containerd/cri/blob/release/1.2/docs/registry.md。

CRI 插件测试指南

本小节假定您已经设置了开发环境(go、git、github.com/containerd/containerd repo 等)。

在发送拉取请求之前,您至少应确保您的更改已通过代码验证、单元测试、集成测试和 CRI 验证测试。

构建

按照 building 说明进行。

CRI 集成测试

  • 运行所有 CRI 集成测试:
make cri-integration
  • 运行特定的 CRI 集成测试:使用 FOCUS 参数指定测试用例。
# 运行与测试字符串 <TEST_NAME> 匹配的 CRI 集成测试
FOCUS=<TEST_NAME> make cri-integration

示例:

FOCUS=TestContainerListStats make cri-integration

CRI 验证测试

CRI验证测试 是一个测试框架,用于验证容器运行时接口(CRI)的实现,如带有cri插件的containerd,是否满足管理pod沙箱、容器、镜像等所需的所有要求。

通过 CRI 验证测试,无需设置 Kubernetes 组件或运行 Kubernetes 端到端测试,就能验证 containerd 的 CRI 一致性。

  • 安装依赖项。
  • 运行上文内置了 cri 插件的 containerd:
containerd -l debug

有关 CRI 验证测试的 更多信息。

节点 E2E 测试

Node e2e test是一个测试 Kubernetes 节点级功能(如管理 pod、挂载卷等)的测试框架。它使用 Kubelet 和其他一些最基本的依赖项启动本地集群,并针对本地集群运行节点功能测试。

目前,e2e-node 测试支持通过 github 上的 Pull Request 注释进行。
在拉取请求的注释中输入"/test all",即可查看已通过 prow bot 与 GCE 托管的 kubernetes 测试服务集成的测试选项列表。
输入 /test pull-containerd-node-e2e 将在你的拉取请求提交上启动节点 e2e 测试运行。

有关 Kubernetes 节点 e2e 测试的 更多信息。

CRICTL 用户指南

本小节假定您已经安装并运行了带有 cri 插件的 containerd

本文档面向希望调试、检查和管理 pod 的开发人员、
容器和容器映像的开发人员。

在生成针对本文档、containerdcontainerd/cri
crictl 生成问题之前,请确保该问题尚未提交过。

安装 crictl

如果您尚未安装 crictl,请安装与您正在使用的
与您正在使用的 cri 插件兼容的版本。如果您是用户,您的部署应该已为您安装了 crictl。如果没有,请从发布的压缩包中获取。
如果您是开发人员,当前的 crictl 版本将在 此处 中指定。
已包含一条辅助命令,用于在正确的版本上安装依赖项:

$ make install-deps
  • 注意:名为 /etc/crictl.yaml 的文件用于配置 crictl
    的文件,这样就不必重复指定用于将 crictl和
    容器运行时进行连接的sock:
$ cat /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: true

下载并检查容器镜像

pull 命令会告诉容器运行时从容器注册中心下载容器镜像。

$ crictl pull busybox...
$ crictl inspecti busybox... displays information about the image.

注意: 如果在运行 crictl 命令时遇到类似于下面的错
时(而你的 containerd 实例已经在运行)

crictl info
FATA[0000] getting status of runtime failed: rpc error: code = Unimplemented desc = unknown service runtime.v1alpha2.RuntimeService

这可能是因为您使用了不正确的 containerd 配置(可能是
来自 Docker 安装)。您需要更新正在运行的 containerd 实例的配置。一种方法如下:

$ mv /etc/containerd/config.toml /etc/containerd/config.bak
$ containerd config default > /etc/containerd/config.toml

直接加载容器镜像

将镜像加载到容器运行时的另一种方法是使用 load
命令。使用加载命令,您可以从文件中将容器镜像注入容器
运行时。首先,你需要创建一个容器镜像压缩包。例如
例如,为使用 Docker 的暂停容器创建镜像压缩包:

$ docker pull registry.k8s.io/pause:3.93.9: Pulling from pause7582c2cc65ef: Pull completeDigest: sha256:7031c1b283388d2c2e09b57badb803c05ebed362dc88d84b480cc47f72a21097Status: Downloaded newer image for registry.k8s.io/pause:3.9registry.k8s.io/pause:3.9
$ docker save registry.k8s.io/pause:3.9 -o pause.tar

然后使用 ctr 将容器镜像加载到容器运行时:

# cri 插件使用 "k8s.io "容器名称空间
$ sudo ctr -n=k8s.io images import pause.tarLoaded image: registry.k8s.io/pause:3.9

列出镜像并检查暂停镜像:

$ sudo crictl images
IMAGE                       TAG                 IMAGE ID            SIZE
docker.io/library/busybox   latest              f6e427c148a76       728kB
registry.k8s.io/pause            3.9                 e6f181688397       311kB
$ sudo crictl inspecti e6f181688397... displays information about the pause image.
$ sudo crictl inspecti registry.k8s.io/pause:3.9... displays information about the pause image.

运行 pod 沙盒(使用配置文件)

$ cat sandbox-config.json
{"metadata": {"name": "nginx-sandbox","namespace": "default","attempt": 1,"uid": "hdishd83djaidwnduwk28bcsb"},"linux": {}
}$ crictl runp sandbox-config.json
e1c83b0b8d481d4af8ba98d5f7812577fc175a37b10dc824335951f52addbb4e
$ crictl pods
PODSANDBOX ID       CREATED             STATE               NAME               NAMESPACE          ATTEMPT
e1c83b0b8d481       2 hours ago         SANDBOX_READY       nginx-sandbox      default            1
$ crictl inspectp e1c8... displays information about the pod and the pod sandbox pause container.
  • 注意:如上所述,如果 ID 是唯一的,则可以使用截断的 ID。
  • 管理 pod 的其他命令包括:stops ID 用于停止运行中的 pod,rmp ID 用于删除 pod 沙盒。

在 Pod 沙盒中创建并运行容器(使用配置文件)

$ cat container-config.json
{"metadata": {"name": "busybox"},"image":{"image": "busybox"},"command": ["top"],"linux": {}
}$ crictl create e1c83 container-config.json sandbox-config.json
0a2c761303163f2acaaeaee07d2ba143ee4cea7e3bde3d32190e2a36525c8a05
$ crictl ps -a
CONTAINER ID        IMAGE               CREATED             STATE               NAME                ATTEMPT
0a2c761303163       docker.io/busybox   2 hours ago         CONTAINER_CREATED   busybox             0
$ crictl start 0a2c
0a2c761303163f2acaaeaee07d2ba143ee4cea7e3bde3d32190e2a36525c8a05
$ crictl ps
CONTAINER ID        IMAGE               CREATED             STATE               NAME                ATTEMPT
0a2c761303163       docker.io/busybox   2 hours ago         CONTAINER_RUNNING   busybox             0
$ crictl inspect 0a2c7... show detailed information about the container

在容器中执行命令

$ crictl exec -i -t 0a2c ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var

显示容器的统计信息

$ crictl stats
CONTAINER           CPU %               MEM                 DISK              INODES
0a2c761303163f      0.00                983kB             16.38kB             6
  • 其他管理容器的命令包括:stop ID 用于停止运行中的容器和 rm ID 用于移除容器。

显示版本信息

$ crictl version
Version:  0.1.0
RuntimeName:  containerd
RuntimeVersion:  v1.7.0
RuntimeApiVersion:  v1

显示 Containerd 和 CRI 插件的状态和配置信息

$ crictl info
{"status": {"conditions": [{"type": "RuntimeReady","status": true,"reason": "","message": ""},{"type": "NetworkReady","status": true,"reason": "","message": ""}]},"cniconfig": {"PluginDirs": ["/opt/cni/bin"],"PluginConfDir": "/etc/cni/net.d","PluginMaxConfNum": 1,"Prefix": "eth","Networks": []},"config": {"containerd": {"snapshotter": "overlayfs","defaultRuntimeName": "runc","defaultRuntime": {"runtimeType": "","runtimePath": "","runtimeEngine": "","PodAnnotations": [],"ContainerAnnotations": [],"runtimeRoot": "","options": {},"privileged_without_host_devices": false,"privileged_without_host_devices_all_devices_allowed": false,"baseRuntimeSpec": "","cniConfDir": "","cniMaxConfNum": 0,"snapshotter": "","sandboxMode": ""},"untrustedWorkloadRuntime": {"runtimeType": "","runtimePath": "","runtimeEngine": "","PodAnnotations": [],"ContainerAnnotations": [],"runtimeRoot": "","options": {},"privileged_without_host_devices": false,"privileged_without_host_devices_all_devices_allowed": false,"baseRuntimeSpec": "","cniConfDir": "","cniMaxConfNum": 0,"snapshotter": "","sandboxMode": ""},"runtimes": {"runc": {"runtimeType": "io.containerd.runc.v2","runtimePath": "","runtimeEngine": "","PodAnnotations": [],"ContainerAnnotations": [],"runtimeRoot": "","options": {"BinaryName": "","CriuImagePath": "","CriuPath": "","CriuWorkPath": "","IoGid": 0,"IoUid": 0,"NoNewKeyring": false,"NoPivotRoot": false,"Root": "","ShimCgroup": "","SystemdCgroup": false},"privileged_without_host_devices": false,"privileged_without_host_devices_all_devices_allowed": false,"baseRuntimeSpec": "","cniConfDir": "","cniMaxConfNum": 0,"snapshotter": "","sandboxMode": "podsandbox"}},"noPivot": false,"disableSnapshotAnnotations": true,"discardUnpackedLayers": false,"ignoreBlockIONotEnabledErrors": false,"ignoreRdtNotEnabledErrors": false},"cni": {"binDir": "/opt/cni/bin","confDir": "/etc/cni/net.d","maxConfNum": 1,"setupSerially": false,"confTemplate": "","ipPref": ""},"registry": {"configPath": "","mirrors": {},"configs": {},"auths": {},"headers": {}},"imageDecryption": {"keyModel": "node"},"disableTCPService": true,"streamServerAddress": "127.0.0.1","streamServerPort": "0","streamIdleTimeout": "4h0m0s","enableSelinux": false,"selinuxCategoryRange": 1024,"sandboxImage": "registry.k8s.io/pause:3.9","statsCollectPeriod": 10,"systemdCgroup": false,"enableTLSStreaming": false,"x509KeyPairStreaming": {"tlsCertFile": "","tlsKeyFile": ""},"maxContainerLogSize": 16384,"disableCgroup": false,"disableApparmor": false,"restrictOOMScoreAdj": false,"maxConcurrentDownloads": 3,"disableProcMount": false,"unsetSeccompProfile": "","tolerateMissingHugetlbController": true,"disableHugetlbController": true,"device_ownership_from_security_context": false,"ignoreImageDefinedVolumes": false,"netnsMountsUnderStateDir": false,"enableUnprivilegedPorts": false,"enableUnprivilegedICMP": false,"enableCDI": false,"cdiSpecDirs": ["/etc/cdi","/var/run/cdi"],"imagePullProgressTimeout": "1m0s","drainExecSyncIOTimeout": "0s","containerdRootDir": "/var/lib/containerd","containerdEndpoint": "/run/containerd/containerd.sock","rootDir": "/var/lib/containerd/io.containerd.grpc.v1.cri","stateDir": "/run/containerd/io.containerd.grpc.v1.cri"},"golang": "go1.20.3","lastCNILoadStatus": "OK","lastCNILoadStatus.default": "OK"
}

更多信息

参见 此处

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/676312.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1987-2022年各省进出口总额数据整理(含进口和出口)(无缺失)

1987-2022年各省进出口总额数据整理&#xff08;含进口和出口&#xff09;&#xff08;无缺失&#xff09; 1、时间&#xff1a;1987-2022年 2、来源&#xff1a;各省年鉴、统计公报 3、指标&#xff1a;进出口总额&#xff08;万美元&#xff09;、进口总额&#xff08;万美…

Vuex介绍和使用

1. 什么是Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式和库。它解决了在大型 Vue.js 应用程序中共享和管理状态的问题&#xff0c;使得状态管理变得更加简单、可预测和可维护。 在 Vue.js 应用中&#xff0c;组件之间的通信可以通过 props 和事件进行&#xff0c…

SCI 1区论文:Segment anything in medical images(MedSAM)[文献阅读]

基本信息 标题&#xff1a;Segment anything in medical images中文标题&#xff1a;分割一切医学图像发表年份: 2024年1月期刊/会议: Nature Communications分区&#xff1a; SCI 1区IF&#xff1a;16.6作者: Jun Ma; Bo Wang(一作&#xff1b;通讯)单位&#xff1a;加拿大多…

文件绕过-Unsafe Fileuoload

文件上传基础 什么是文件上传 将客户端数据以文件形式封装通过网络协议发送到服务器端&#xff0c;在服务器端解析数据&#xff0c;最终在服务端硬盘上作为真实的文件保存。 通常一个文件以HTTP协议进行上传时&#xff0c;将以POST请求发送至Web服务器&#xff0c;Web服务器…

【初中生讲机器学习】6. 分类算法中常用的模型评价指标有哪些?here!

创建时间&#xff1a;2024-02-07 最后编辑时间&#xff1a;2024-02-09 作者&#xff1a;Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏&#xff0c;很高兴遇见你~ 我是 Geeker_LStar&#xff0c;一名初三学生&#xff0c;热爱计算机和数学&#xff0c;我们一起加…

【原创 附源码】Flutter海外登录--Google登录最详细流程

最近接触了几个海外登录的平台&#xff0c;踩了很多坑&#xff0c;也总结了很多东西&#xff0c;决定记录下来给路过的兄弟坐个参考&#xff0c;也留着以后留着回顾。更新时间为2024年2月8日&#xff0c;后续集成方式可能会有变动&#xff0c;所以目前的集成流程仅供参考&#…

[UI5 常用控件] 08.Wizard,NavContainer

文章目录 前言1. Wizard1.1 基本结构1.2 属性1.2.1 Wizard&#xff1a;complete1.2.2 Wizard&#xff1a;finishButtonText1.2.3 Wizard&#xff1a;currentStep1.2.4 Wizard&#xff1a;backgroundDesign1.2.5 Wizard&#xff1a;enableBranching1.2.6 WizardStep&#xff1a;…

PKI - 03 密钥管理(如何进行安全的公钥交换)

文章目录 Pre密钥管理面临的挑战安全密钥管理的几种方式手动密钥交换与确认受信任的介绍 Pre PKI - 02 对称与非对称密钥算法 密钥管理面临的挑战 密钥管理面临的挑战主要包括以下几点&#xff1a; 安全的公钥交换&#xff1a;在使用基于非对称密钥算法的服务之前&#xff0c…

清理神器CleanMyMac X 空间透镜——可视化您的磁盘空间 空间透镜有什么用

不久前&#xff0c;CleanMyMac X 发布了一个新功能&#xff1a; 空间透镜 相信有非常多的小伙伴和小编一样&#xff0c; 对这个功能一脸问号 这啥玩意儿&#xff1f;&#xff1f;&#xff1f; 今天就让我们深入了解一下&#xff0c; CleanMyMac X 的空间透镜功能。 - 更好…

嵌入式单片机中晶振的工作原理

晶振在单片机中是必不可少的元器件&#xff0c;只要用到CPU的地方就必定有晶振的存在&#xff0c;那么晶振是如何工作的呢&#xff1f; 什么是晶振 晶振一般指晶体振荡器&#xff0c;晶体振荡器是指从一块石英晶体上按一定方位角切下的薄片&#xff0c;简称为晶片。 石英晶体谐…

吉他学习:识谱,认识节奏,视唱节奏,节拍器的使用

第九课 识谱https://m.lizhiweike.com/lecture2/29362692 第十课 基础乐理(二)——节奏篇https://mp.csdn.net/mp_blog/creation/editor?spm=1011.2124.3001.6192

Redis核心技术与实战【学习笔记】 - 27.限制Redis Cluster规模的因素(通信开销)

简述 Redis Cluster 能保存的数据量以及支撑的吞吐量&#xff0c;跟集群实例规模相关。 Redis 官方给出了 Redis Cluster 的规模上线&#xff0c;就是一个集群运行 1000 个实例。 其实&#xff0c;限定 Redis Cluster 集群规模的一个关键因素就是&#xff0c;实例间的通信开销…

Vue源码系列讲解——虚拟DOM篇【三】(更新子节点)

1. 前言 在上一篇文章中&#xff0c;我们了解了Vue中的patch过程&#xff0c;即DOM-Diff算法。并且知道了在patch过程中基本会干三件事&#xff0c;分别是&#xff1a;创建节点&#xff0c;删除节点和更新节点。创建节点和删除节点都比较简单&#xff0c;而更新节点因为要处理…

12个最常用的matplotlib图例 !!

文章目录 1、折线图 2、散点图 3、直方图 4、柱状图 5、箱线图 6、热力图 7、饼图 8、面积图 9、等高线图 10、3D图 11、时间序列图 12、树状图 总结 1、折线图 折线图&#xff08;Line Plot&#xff09;&#xff1a;用于显示数据随时间或其他连续变量的变化趋势。在实际项目中…

【Linux驱动】块设备驱动(三)—— 块设备读写(不使用请求队列)

并非每种块设备都会用到请求队列&#xff0c;从上节可以知道&#xff0c;请求队列的作用是管理和调用IO请求&#xff0c;那么反过来想&#xff0c;如果IO请求较少&#xff0c;那就可以无需使用请求队列。在以下情况中&#xff0c;可以不使用请求队列。 单任务环境: 当系统中只有…

VRRP配置

目录 网络拓扑图 配置要求 配置步骤 网络拓扑图 配置要求 按照图示配置 IP 地址和网关在 SW1&#xff0c;SW2&#xff0c;SW3 上创建 Vlan10 和 Vlan20&#xff0c;对应 IP 网段如图&#xff0c;交换机之间链路允许所有 VLAN 通过在 SW1 和 SW2 上配置 VRRP&#xff0c;要求…

在windows server2016部署域控服务器DC

1.正常配置vmware虚拟机基础环境 2.启动虚拟机&#xff0c;会先到efi network&#xff0c;等待几分钟 3.进入boot manager&#xff0c;选择启动方式&#xff0c;记得提示CD启动的时候需要按回车&#xff0c;不然又会回到这个界面 4.选择安装版本为桌面版&#xff08;开始直接…

无题2024

念旧 阿悠悠 专辑&#xff1a;念旧 发行时间 2019-08-25 念旧 播报编辑讨论1上传视频 阿悠悠演唱歌曲 《念旧》是由一博作词&#xff0c;一博和张池作曲&#xff0c;阿悠悠演唱的歌曲&#xff0c;发行于2019年8月25日。 [1]收录于同名专辑《念旧》中。 相关星图 查…

(四)elasticsearch 源码之索引流程分析

https://www.cnblogs.com/darcy-yuan/p/17024341.html 1.概览 前面我们讨论了es是如何启动&#xff0c;本文研究下es是如何索引文档的。 下面是启动流程图&#xff0c;我们按照流程图的顺序依次描述。 其中主要类的关系如下: 2. 索引流程 (primary) 我们用postman发送请求&…

Windows Server 2025 Hyper-V 新变化

今天简单跟大家聊聊Windows Server 2025 Hyper-V一些新功能新变化&#xff0c;具体如下&#xff1a; 在 VM 之间共享 GPU 随着图形处理器的重要性日益增加&#xff0c;特别是由于它们在 AI 应用程序中的核心作用&#xff0c;Hyper-V 中对 GPU 的现有支持已不再足够。到目前为…