一个关于新手使用Kubernetes作为VIM来通过Tacker部署CNF的故事
章节索引
1. 首先
2. 环境
3. 安装步骤
4. 发生的错误
5. 总结
请提供网址作为参考
-
- ETSI NFV-SOL CNF (Containerized VNF) Deployment
-
- VNF と CNF の違い
-
- VNF Package
-
- Kubernetes VIM Installation
-
- Master NodeにPodをデプロイするための設定
- Kuryr installation as a Kubernetes network addon
首先
你好。我是一名新进员工,已经在这里工作了大约3个月。
この記事では NFV という言葉すら知らなかった新人が Install via Devstack を参考にして DevStack 環境をインストールし、VIM として OpenStack と Kubernetes を登録するまでの手順と発生したエラーを複数の章に分けて記載していきます。
- 第 1 章: 新人が DevStack 上で Tacker を動かそうとする話
Install via Devstack を実際に試します。
- 第 2 章: 新人が DevStack 上で TOSCA を使用して VNF を VM としてデプロイする話
ETSI NFV-SOL VNF Deployment as VM with TOSCA を実際に試します。
- 第 3 章: 新人が DevStack 上で LCM Operation User Data を使用して VNF を VM としてデプロイする話
将ETSI NFV-SOL VNF部署为具有LCM操作用户数据的虚拟机,并实际进行测试。
- 第 4 章: この記事です。
我们将实际尝试 ETSI NFV-SOL CNF(容器化虚拟网络功能)部署。
这次安装后,我整理了我所调查的术语如下:
CNF (Containerized Network Function)
提供容器化的网络功能。
CSAR(云服务存档)
这是一个使用ZIP文件格式的存档文件。其结构符合TOSCA Simple Profile YAML v1.2规范。
这里的文件结构的归档已经在VNF Package中进行了描述。
环境
请阅读《新人在DevStack上尝试运行Tacker的故事》和《新人在DevStack上使用TOSCA将VNF部署为虚拟机的故事》,我在ESXi上安装了DevStack,并对环境进行了一些配置。
安装步骤
这个步骤在本环境中成功完成了安装。
将发生的错误总结在步骤完成之前的第4个错误中。
用户和目录
使用stack用户执行。
sudo -u stack -i
自分で作成したファイルを配置する work ディレクトリを作成します。
mkdir ~/work/
work ディレクトリに移動します。
cd ~/work
Kubernetes 環境の準備 (kubeadm)
Tacker が ETSINFV-SOL コンテナ化 VNF を Kubernetes にデプロイする方法について記載します。
本環境では kuryr-kubernetes が動作しないため、Devstack 内の Kubernetes を VIM として利用できませんでした。
この kuryr-kubernetes は VM を再起動すると停止し、動作しなくなります。
原因は現在も不明です。
そのため、新しい VM 上に kubeadm で Kubernetes を起動させ、VIM として利用します。
この手順は Devstack を動作させている環境とは別の環境で動作させなければなりません。
Devstack を動作させている環境では etcd が動作しています。
そのため、同環境へ新たに Kubernetes を動作させると etcd が競合してしまいます。
本手順完了後の環境は下記の図のようになります。
この図は 1. はじめに で述べた章をすべて実施済みの状態です。
禁用交换
由于Kubernetes在初始化时发生错误,需要禁用swap。
创建 fstab 的备份文件。
sudo cp -ai /etc/fstab{,.default}
禁用交换操作。
注销以下项目。
$ vim /etc/fstab
/swap.img none swap sw 0 0
我确认。
$ diff /etc/fstab{.default,}
12c12
< /swap.img none swap sw 0 0
---
> #/swap.img none swap sw 0 0
这个设置将导致在重新启动后启动时交换被禁用的状态,但如果要在不重新启动的情况下禁用交换,则执行以下操作。
sudo swapoff -a
カーネルパラメータの設定
ネットワークブリッジを通過するパケットに対し iptables ルールを適用するかどうかを指定するカーネルパラメータ net.bridge.bridge-nf-call-iptables を確認します。
1 と設定されている場合は問題ありません。
$ cat /proc/sys/net/bridge/bridge-nf-call-iptables
1
0 と設定されている場合は以下を実行することで設定を 1 に変更します。
echo net.bridge.bridge-nf-call-iptables = 1 > /etc/sysctl.d/99-bridge-nf-call-iptables
sysctl -p /etc/sysctl.d/99-bridge-nf-call-iptables
更改 Docker 驱动程序
从Kubernetes v1.21开始,kubeadm的标准cgroup驱动程序已从cgroupfs更改为systemd。因此,需要检查Docker的驱动程序,并在必要时进行更改为systemd。
我确定。 (Wǒ .)
$ docker info | grep Cgroup
Cgroup Driver: cgroupfs
Cgroup Version: 1
daemon.json のバックアップを作成します。
sudo cp -ai /etc/docker/daemon.json{,.default}
daemon.json ファイルに下記を追記します。
$ sudo vim /etc/docker/daemon.json
・・・
"exec-opts": ["native.cgroupdriver=systemd"],
・・・
执行daemon的重新加载和docker.service的重新启动。
sudo systemctl daemon-reload
sudo systemctl restart docker.service
設定を確認します。
$ docker info | grep Cgroup
Cgroup Driver: systemd
Cgroup Version: 1
主节点的设置
我们将搭建Kubernetes集群。
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16
I0715 06:29:47.841987 107552 version.go:255] remote version is much newer: v1.24.3; falling back to: stable-1.22
[init] Using Kubernetes version: v1.22.12
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local yoshitest] and IPs [10.96.0.1 10.100.2.210]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost yoshitest] and IPs [10.100.2.210 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost yoshitest] and IPs [10.100.2.210 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 17.502563 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.22" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node yoshitest as control-plane by adding the labels: [node-role.kubernetes.io/master(deprecated) node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node yoshitest as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: slx8x6.kvl1eks1u9auzbm6
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 10.100.2.210:6443 --token slx8x6.kvl1eks1u9auzbm6 \
--discovery-token-ca-cert-hash sha256:06c48716c874f3565250f79837e07db67e7e98e493d45072818a335c07f0a633
.kube ディレクトリをホームディレクトリに配置します。
これにより kubectl コマンドなどが使用可能になります。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Kubernetes 将检查其运行状态。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
yoshitest Ready control-plane,master 11m v1.22.3
$ kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-78fcd69978-bflnm 0/1 ContainerCreating 0 11m
kube-system coredns-78fcd69978-dh6kg 0/1 ContainerCreating 0 11m
kube-system etcd-yoshitest 1/1 Running 1 11m
kube-system kube-apiserver-yoshitest 1/1 Running 1 11m
kube-system kube-controller-manager-yoshitest 1/1 Running 1 11m
kube-system kube-proxy-p84m8 1/1 Running 0 11m
kube-system kube-scheduler-yoshitest 1/1 Running 1 11m
CNI 安装
将Calico作为CNI插件安装。
工作目录将设定为~/work/calico。
mkdir -p ~/work/calico
cd ~/work/calico
下载所需的安装文件。
curl https://projectcalico.docs.tigera.io/manifests/tigera-operator.yaml -O
curl https://projectcalico.docs.tigera.io/manifests/custom-resources.yaml -O
将 customer-resources.yaml 文件中 spec.calicoNetwork.ipPools.cidr 的值更改为使用 kubeadm init –pod-network-cidr= 指定的值。
$ vim custom-resources.yaml
・・・
spec:
# Configures Calico networking.
calicoNetwork:
# Note: The ipPools section cannot be modified post-install.
ipPools:
- blockSize: 26
cidr: 10.244.0.0/16
・・・
安装 Calico。
kubectl apply -f tigera-operator.yaml
kubectl apply -f custom-resources.yaml
您好。「起动确认します。」的中文翻译可以是「进行启动确认。」。
$ kubectl get pod -n tigera-operator
NAME READY STATUS RESTARTS AGE
tigera-operator-d8cbfddcc-dmfww 1/1 Running 0 29s
$ kubectl get pod -n calico-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-7f87b64bd9-fzshn 1/1 Running 0 5m13s
calico-node-dgwhm 1/1 Running 0 5m13s
calico-typha-5fdf9ffc5c-bvmp9 1/1 Running 0 5m14s
删除 Master 节点的 Taint 信息
本次我们不会创建Worker节点,只在Master节点上运行。
为了防止Pod在Master节点上部署,Master节点默认添加了一个名为node-role.kubernetes.io/master:NoSchedule的Taint。
由于没有准备Worker节点,无法部署Pod,因此在本环境中将删除此Taint信息。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
yoshitest Ready control-plane,master 33m v1.22.3
$ kubectl taint nodes yoshitest node-role.kubernetes.io/master:NoSchedule-
node/yoshitest untainted
确认启动样本清单。
请准备以下示例文件作为manifest的文件,并尝试启动Pod作为示例。
$ cat << _EOF_ > sample.yaml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
_EOF_
启动。
kubectl apply -f sample.yaml
我会确认。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-66b6c48dd5-glcrt 1/1 Running 0 10m
nginx-deployment-66b6c48dd5-t7s4n 1/1 Running 0 10m
Kubernetes 虚拟机管理器 (VIM)
请在基本上已经运行Devstack的机器上进行以下工作。
只有在 Kubernetes Master 节点上才需要进行[VIM用配置文件的创建所需信息获取]。
获取创建VIM配置文件所需的信息
在Kubernetes Master节点上执行此步骤,收集所需用于创建文件的以下值。
- auth_url
我的 IP 地址是:<自身的 IP>:6443。
如果使用命令来查询,请按以下方式操作。
$ kubectl cluster-info
Kubernetes control plane is running at https://10.100.2.210:6443
CoreDNS is running at https://10.100.2.210:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
- bearer_token
确认包含有”ベアトークン”的Kubernetes Secret名称。
在Kubernetes数据模型中,包含在.data中的值以Base64形式进行编码,因此如果要将其用作裸令牌,需要使用base64 –decode或base64 -d命令对其进行解码。
$ kubectl get secret
NAME TYPE DATA AGE
default-token-qm98x kubernetes.io/service-account-token 3 59m
$ TOKEN=$(kubectl get secret default-token-qm98x -o jsonpath="{.data.token}" | base64 --decode) && echo $TOKEN
eyJhbGciOiJSUzI1NiIsImtpZCI6IjNGVXpEeGIxbU9xMGY0NEpEeGt4bkhrMDJidU9GSUVMUFN0RlRGMi16R1kifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tcW05OHgiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImY2MGQxYWNlLTU3YmQtNDY1OC05YTBjLWIxMTdmMzNmY2EyYiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.kPwKalaP5123zJ7Lw29PCHpT_mU5uwjUkbtKFbn9rtCfUAXCEwOveTFf3F9s08RudaQKy5CJQrj5TqAS_7lQ2EQePKBL6_pW9YKxqUUNRw8krF7xa-ghTON2B0HKdTl51ZMPKwgjLkydrvH7JQT5C11WBbot0auct-m2wBlL1M8ahUdaHcv--nCHm4JF7NKMd8wW0ASmGBGV3Fei8GEUVMCp-GicrDzp8A0dgbVY9NZkWoed4cP6eSsVN_FaHwt2V4SqrvgjkNvDttFID9sL7UkcKGz8KIJSLzQnX6DVDuUyXjSpz7TsvAN2-DV2oO8fn35WlhLw9YZQ3t264qs0bQ
在使用此令牌之前,用户需要将管理员角色应用于此令牌。
$ kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole cluster-admin --serviceaccount=default:default
clusterrolebinding.rbac.authorization.k8s.io/cluster-admin-binding created
- ssl_ca_cert
获取有关 Kubernetes 集群身份验证的详细信息。
$ kubectl get secrets default-token-qm98x -o jsonpath="{.data.ca\.crt}" | base64 --decode
-----BEGIN CERTIFICATE-----
MIIC/jCCAeagAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
cm5ldGVzMB4XDTIyMDcxNTA2Mjk0OVoXDTMyMDcxMjA2Mjk0OVowFTETMBEGA1UE
AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK6q
Q/LNRChV6tw2ucfNhV8sBBvWyt+0KtFyDA16h7Tm49wBBzx/Y/cF4UGBFUETcYgA
9zUbrcPqnBeyVXD9Td5R0y/oqPXuX3wBzetalcSe3OlZiAiG28asWf1jaXGCDgmk
hfQBz2OQi0jO98XoG014ok7Ortgz0v6ZV/9tcGPCwxlsERRXCYpeytHE4aCI/aky
8fnT7SGQ506WD7x4DnSYluH5ceH3NeQ56qIsLZUk4G75LVSTr26r7bds6n81urgV
pJi9OMaxA1SWveEoH5serSy5nNfLzjFZhS7r3KDkUl3yokltlQq61K3rHLNQoz+Z
+BpklMSQj8a9thkylj8CAwEAAaNZMFcwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB
/wQFMAMBAf8wHQYDVR0OBBYEFFNNpaDF4hs8BcdxmNoUyUcvVomAMBUGA1UdEQQO
MAyCCmt1YmVybmV0ZXMwDQYJKoZIhvcNAQELBQADggEBAF72CNi5EUFeUYLxP9Qf
buSD2hQaDcgBr+W9de/BFGXF1jm+lUag92Jd7+EIHwt27Pf4mRpZLce6pB3bhzQ6
oc7b5vs9k3B+3gByPKW52RZrz7cXL1nfz2TxgBEqiruZiviZiZB7f/KkMZDeU+fW
c5R96oBr4/eGqtTh2P6q5UKYixOoYjhnZGCQOYG+SJInIqKQUBmbqaazCXCZNxdv
1fPzBe73AnMdiFl9AzEc38htf912dh5SRzKmkH47cU/m+7GbzXLsjhOtGWay/rV4
thpePCADCWBYrL62VZoRJs+VW7jNPTJwTMkfUuKN6KwSXugJVvAGRVsrV9rnTuOO
sbQ=
-----END CERTIFICATE-----
您可以确认API端点和访问令牌是可用的。
$ curl -k https://10.100.2.210:6443/api/ -H "Authorization: Bearer $TOKEN"
{
"kind": "APIVersions",
"versions": [
"v1"
],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "10.100.2.210:6443"
},
{
"clientCIDR": "10.96.0.0/12",
"serverAddress": "10.96.0.1:443"
}
]
}
创建VIM的配置文件
使用获取到的信息来创建配置文件。
以下步骤将在运行Devstack的计算机上执行。
cat << _EOF_ > ~/work/vim-k8s.yaml
auth_url: "https://10.100.2.210:6443"
project_name: "default"
bearer_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IjNGVXpEeGIxbU9xMGY0NEpEeGt4bkhrMDJidU9GSUVMUFN0RlRGMi16R1kifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tcW05OHgiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImY2MGQxYWNlLTU3YmQtNDY1OC05YTBjLWIxMTdmMzNmY2EyYiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.kPwKalaP5123zJ7Lw29PCHpT_mU5uwjUkbtKFbn9rtCfUAXCEwOveTFf3F9s08RudaQKy5CJQrj5TqAS_7lQ2EQePKBL6_pW9YKxqUUNRw8krF7xa-ghTON2B0HKdTl51ZMPKwgjLkydrvH7JQT5C11WBbot0auct-m2wBlL1M8ahUdaHcv--nCHm4JF7NKMd8wW0ASmGBGV3Fei8GEUVMCp-GicrDzp8A0dgbVY9NZkWoed4cP6eSsVN_FaHwt2V4SqrvgjkNvDttFID9sL7UkcKGz8KIJSLzQnX6DVDuUyXjSpz7TsvAN2-DV2oO8fn35WlhLw9YZQ3t264qs0bQ"
ssl_ca_cert: "-----BEGIN CERTIFICATE-----
MIIC/jCCAeagAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
cm5ldGVzMB4XDTIyMDcxNTA2Mjk0OVoXDTMyMDcxMjA2Mjk0OVowFTETMBEGA1UE
AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK6q
Q/LNRChV6tw2ucfNhV8sBBvWyt+0KtFyDA16h7Tm49wBBzx/Y/cF4UGBFUETcYgA
9zUbrcPqnBeyVXD9Td5R0y/oqPXuX3wBzetalcSe3OlZiAiG28asWf1jaXGCDgmk
hfQBz2OQi0jO98XoG014ok7Ortgz0v6ZV/9tcGPCwxlsERRXCYpeytHE4aCI/aky
8fnT7SGQ506WD7x4DnSYluH5ceH3NeQ56qIsLZUk4G75LVSTr26r7bds6n81urgV
pJi9OMaxA1SWveEoH5serSy5nNfLzjFZhS7r3KDkUl3yokltlQq61K3rHLNQoz+Z
+BpklMSQj8a9thkylj8CAwEAAaNZMFcwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB
/wQFMAMBAf8wHQYDVR0OBBYEFFNNpaDF4hs8BcdxmNoUyUcvVomAMBUGA1UdEQQO
MAyCCmt1YmVybmV0ZXMwDQYJKoZIhvcNAQELBQADggEBAF72CNi5EUFeUYLxP9Qf
buSD2hQaDcgBr+W9de/BFGXF1jm+lUag92Jd7+EIHwt27Pf4mRpZLce6pB3bhzQ6
oc7b5vs9k3B+3gByPKW52RZrz7cXL1nfz2TxgBEqiruZiviZiZB7f/KkMZDeU+fW
c5R96oBr4/eGqtTh2P6q5UKYixOoYjhnZGCQOYG+SJInIqKQUBmbqaazCXCZNxdv
1fPzBe73AnMdiFl9AzEc38htf912dh5SRzKmkH47cU/m+7GbzXLsjhOtGWay/rV4
thpePCADCWBYrL62VZoRJs+VW7jNPTJwTMkfUuKN6KwSXugJVvAGRVsrV9rnTuOO
sbQ=
-----END CERTIFICATE-----"
type: "kubernetes"
_EOF_
Kubernetes VIM 注册
将 Kubernetes VIM 注册到 Tacker 上。
test-vim-k8s-kubeadm 是要注册的 Kubernetes VIM 的名称。
$ openstack vim register --config-file vim-k8s.yaml test-vim-k8s-kubeadm --fit-width
+----------------+---------------------------------------------------------------------------------------------------------+
| Field | Value |
+----------------+---------------------------------------------------------------------------------------------------------+
| auth_cred | { |
| | "bearer_token": "***", |
| | "ssl_ca_cert": "b'gAAAAABi0SJYjdfgr98GZaz2sFM5kRw8ZDgZUWkWFwdqQaE1uRLcOiQz3qW4Si66ECS7vApgPHieINreB |
| | k4ECVvZH9CUGyQWCW1FvVsM7U_6M2jpVjsPDTE9s2h78WI4OIA_qw24zQtafubWuWmMeAv2h3ZtIeeo8vxrxMt6UsVNlpgyFrDE6fyG |
| | 0zZ7j9-HFFbHxTUXrr75maiBqQISmzpxvcG-URCyb- |
| | qdJIqPKSZ38isVlzpU5NpgEuuTxqMBdNPADGzUk0eGDiBHNLRjNQ1j-braFxFR9iXfxpHcsLbKtZztaacO- |
| | uJEjtpL1yXZ1lPbwGXurwWf4j2UzsxrnsWoHR1rdNV5PCnefIj- |
| | PIEub_kVOWSF33YuFqHgR7XbkAmMGJalRzE521rCGA64BlG7k1Es- |
| | SyN89YCeEEtnIVf6Kk3ylXfnw0SIefuN48VSj0UV1WJlkcEzXPTAEWueUIjj9pAxaaCW- |
| | znFpqv4_3NZDyG5RYEuDqNo8pi7Vj4kBsT9NK-RcCeAg3cCQcaKsi_SD0NQ0NoWQd5eKWelSeDxTzhTlYpIN_SD7f85ab- |
| | pKPrp4x_F-rPgTcOchrtYBQ3yZvg-zNihmuQLe1yKa_Hf9RjKzc5_I_t4pjoPy140n3QyefuM8yGN973MovEXe8WrjcS_z02VHs_nYB |
| | 1snD4vxhnbUVxNy0TbnAvcujVR_Y2jzw71iUsNVVwXLT3-81xcs5T7B6m-aFH0icyLQy3Ixvj-mm4GVbya8xCGidIaF1iIBV-NXHUng |
| | 0jmsGxRnoOfmLnUef1ek_TFYLmv43cbhbLLdiaPMMWdYdhN5z7AoJiWhL6cVlKmsd1WWKjBPW_GqQgFnlqN1l6CeL5G5_GFfsulcLxk |
| | b06Astvyvv0yMozjHgBMI79WbYmOyqo0NnMCkJFnJLAumP-jy_RtHeKpV8tq41j7BSm-ehc2vdgiWSuCXI5m0J49sDv9yQ631UBQmTf |
| | Nve1ANonQBIB6_sMon52chThE0JL6QtX_N4y0pe0HCyibQAh5a6d0qo2yUAQXS9pPctPkXw7IQpCi2pfr6WmD4SxY5GVegjZg6ySlY6 |
| | X-yShYHw88_ixnulGnLZDcXZp9Y14XwYCGOdY25wekuuvronkKJVnb7cedDV6jj8jTYwkLBuQLfAeJI7nG78DsrOs- |
| | PlsVv4M2hgCgEbDRKckw9ZHcnPAKSGYGP-ongmwhobbkRYLCi8qSuSuCsUT47AvGjsC7yOUDVk0iX-DrQ2V5R-Nns- |
| | pWOj25kz5EB0FxNkAWjVjyMaXYw3Ic3_p_hciOj6eE1CtIsVncHF50TlXVkOMrsbzgpH7zWRrbHh4VFKuk66Zrtgh- |
| | iGv8LkhpOqLoG7x6ayfVmxjzZU2i--F4AKc8EBPXj-_05n6EeOgIEe4szLpUUy_UfeHsYhgkEeGkWWA6RR0HpzF- |
| | uwKnsX1aMfCdFTUmnuvrJWnRJhAsMG-G3sChGo90_G5nNhbXMf6YWcMk8pocNjvVNLJ6vqvgH5aEsnSklbmI2XYHbFRgbCeKRJp'", |
| | "auth_url": "https://10.100.2.210:6443", |
| | "username": "None", |
| | "key_type": "barbican_key", |
| | "secret_uuid": "***", |
| | "password": "***" |
| | } |
| auth_url | https://10.100.2.210:6443 |
| created_at | 2022-07-15 08:16:25.496115 |
| description | |
| id | e31459a6-1380-4fd8-930b-a70dc0500614 |
| is_default | False |
| name | test-vim-k8s-kubeadm |
| placement_attr | { |
| | "regions": [ |
| | "calico-apiserver", |
| | "calico-system", |
| | "default", |
| | "kube-node-lease", |
| | "kube-public", |
| | "kube-system", |
| | "tigera-operator" |
| | ] |
| | } |
| project_id | cd492cafc33c4d6b878ee570f6aeae21 |
| status | PENDING |
| type | kubernetes |
| updated_at | None |
| vim_project | { |
| | "name": "default" |
| | } |
+----------------+---------------------------------------------------------------------------------------------------------+
确认已注册VIM的状态是否为REACHABLE。
$ openstack vim list
+--------------------------------------+----------------------+----------------------------------+------------+------------+-----------+
| ID | Name | Tenant_id | Type | Is Default | Status |
+--------------------------------------+----------------------+----------------------------------+------------+------------+-----------+
| e31459a6-1380-4fd8-930b-a70dc0500614 | test-vim-k8s-kubeadm | cd492cafc33c4d6b878ee570f6aeae21 | kubernetes | False | REACHABLE |
+--------------------------------------+----------------------+----------------------------------+------------+------------+-----------+
我們將定義一個環境變數 VIM ID。
export VIM_ID=e31459a6-1380-4fd8-930b-a70dc0500614
VNF包的准备工作
VNF包中需要包含CNF定义,除了VNFD。
创建 VNF 包的目录
创建一个目录来放置VNF软件包。
mkdir -p ~/work/deployment/{TOSCA-Metadata,Definitions,Files/kubernetes}
创建Kubernetes对象文件
CSAR VNF 包必须包含定义要部署的 Kubernetes 资源的对象文件。
根据不同的 yaml 文件内容,可以创建 Kubernetes API 资源。
创建一个简单的部署资源。
cat << _EOF_ > ~/work/deployment/Files/kubernetes/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: curry-probe-test001
namespace: default
spec:
replicas: 1
selector:
matchLabels:
selector: curry-probe-test001
template:
metadata:
labels:
selector: curry-probe-test001
app: webserver
spec:
containers:
- name: nginx-liveness-probe
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
- image: celebdor/kuryr-demo
imagePullPolicy: IfNotPresent
name: kuryr-demo-readiness-probe
ports:
- containerPort: 8080
protocol: TCP
_EOF_
インスタンス化パラメーターに vdu_mapping が含まれていない場合、このファイルの metadata.name は、デプロイメントフレーバー定義ファイルの対応する VDU の properties.name と同じである必要があります。
今回の手順では metadata.name は後程作成する helloworld3_df_simple.yaml ファイルの topology_template.node_templates.VDU1.properties.name と同じです。
创建TOSCA.meta文件
TOSCA.Meta文件包含了TOSCA.Meta文件、CSAR版本和定义文件的信息。此外,还需要Artifact文件的名称、内容类型、加密方式以及Artifact文件的哈希值。这里的Artifact文件指的是所创建的对象文件。
获取Artifact文件的哈希值。
$ sha256sum ~/work/deployment/Files/kubernetes/deployment.yaml
4154adca79b0dc3829f69c82758736df674ffdd89603b4e827bd81afab6b4028 deployment/Files/kubernetes/deployment.yaml
TOSCA.meta ファイルを作成します。
cat << _EOF_ > ./deployment/TOSCA-Metadata/TOSCA.meta
TOSCA-Meta-File-Version: 1.0
Created-by: dummy_user
CSAR-Version: 1.1
Entry-Definitions: Definitions/helloworld3_top.vnfd.yaml
Name: Files/kubernetes/deployment.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 4154adca79b0dc3829f69c82758736df674ffdd89603b4e827bd81afab6b4028
_EOF_
下載 ETSI 定義文件。
请下载官方文件。
ETSI GS NFV-SOL 001 根据 TOSCA 规范定义了 VNFD 的结构和格式。
cd ~/work/deployment/Definitions
wget https://forge.etsi.org/rep/nfv/SOL001/raw/v2.6.1/etsi_nfv_sol001_common_types.yaml
wget https://forge.etsi.org/rep/nfv/SOL001/raw/v2.6.1/etsi_nfv_sol001_vnfd_types.yaml
创建 VNFD
由于在Kubernetes资源文件中指定了CNF所需的所有组件,因此VNFD中不包含Kubernetes资源信息,如VDU、连接点和虚拟链接。
创建包含CNF定义的VNFD文件。
cat << _EOF_ > ~/work/deployment/Definitions/helloworld3_top.vnfd.yaml
tosca_definitions_version: tosca_simple_yaml_1_2
description: Sample VNF
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
- helloworld3_types.yaml
- helloworld3_df_simple.yaml
topology_template:
inputs:
selected_flavour:
type: string
description: VNF deployment flavour selected by the consumer. It is provided in the API
node_templates:
VNF:
type: company.provider.VNF
properties:
flavour_id: { get_input: selected_flavour }
descriptor_id: b1bb0ce7-ebca-4fa7-95ed-4840d7000003
provider: Company
product_name: Sample VNF
software_version: '1.0'
descriptor_version: '1.0'
vnfm_info:
- Tacker
requirements:
#- virtual_link_external # mapped in lower-level templates
#- virtual_link_internal # mapped in lower-level templates
_EOF_
VNF のパラメータータイプとデフォルト値を定義します。
cat << _EOF_ > ~/work/deployment/Definitions/helloworld3_types.yaml
tosca_definitions_version: tosca_simple_yaml_1_2
description: VNF type definition
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
node_types:
company.provider.VNF:
derived_from: tosca.nodes.nfv.VNF
properties:
descriptor_id:
type: string
constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d7000003 ] ]
default: b1bb0ce7-ebca-4fa7-95ed-4840d7000003
descriptor_version:
type: string
constraints: [ valid_values: [ '1.0' ] ]
default: '1.0'
provider:
type: string
constraints: [ valid_values: [ 'Company' ] ]
default: 'Company'
product_name:
type: string
constraints: [ valid_values: [ 'Sample VNF' ] ]
default: 'Sample VNF'
software_version:
type: string
constraints: [ valid_values: [ '1.0' ] ]
default: '1.0'
vnfm_info:
type: list
entry_schema:
type: string
constraints: [ valid_values: [ Tacker ] ]
default: [ Tacker ]
flavour_id:
type: string
constraints: [ valid_values: [ simple ] ]
default: simple
flavour_description:
type: string
default: "falvour"
requirements:
- virtual_link_external:
capability: tosca.capabilities.nfv.VirtualLinkable
- virtual_link_internal:
capability: tosca.capabilities.nfv.VirtualLinkable
_EOF_
VNF 入力のパラメータータイプを定義します。
cat << _EOF_ > ~/work/deployment/Definitions/helloworld3_df_simple.yaml
tosca_definitions_version: tosca_simple_yaml_1_2
description: Simple deployment flavour for Sample VNF
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
- helloworld3_types.yaml
topology_template:
inputs:
descriptor_id:
type: string
descriptor_version:
type: string
provider:
type: string
product_name:
type: string
software_version:
type: string
vnfm_info:
type: list
entry_schema:
type: string
flavour_id:
type: string
flavour_description:
type: string
substitution_mappings:
node_type: company.provider.VNF
properties:
flavour_id: simple
requirements:
virtual_link_external: []
node_templates:
VNF:
type: company.provider.VNF
properties:
flavour_description: A simple flavour
VDU1:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: curry-probe-test001
description: kubernetes controller resource as VDU
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 3
policies:
- scaling_aspects:
type: tosca.policies.nfv.ScalingAspects
properties:
aspects:
vdu1_aspect:
name: vdu1_aspect
description: vdu1 scaling aspect
max_scale_level: 2
step_deltas:
- delta_1
- vdu1_initial_delta:
type: tosca.policies.nfv.VduInitialDelta
properties:
initial_delta:
number_of_instances: 1
targets: [ VDU1 ]
- vdu1_scaling_aspect_deltas:
type: tosca.policies.nfv.VduScalingAspectDeltas
properties:
aspect: vdu1_aspect
deltas:
delta_1:
number_of_instances: 1
targets: [ VDU1 ]
- instantiation_levels:
type: tosca.policies.nfv.InstantiationLevels
properties:
levels:
instantiation_level_1:
description: Smallest size
scale_info:
vdu1_aspect:
scale_level: 0
instantiation_level_2:
description: Largest size
scale_info:
vdu1_aspect:
scale_level: 2
default_level: instantiation_level_1
- vdu1_instantiation_levels:
type: tosca.policies.nfv.VduInstantiationLevels
properties:
levels:
instantiation_level_1:
number_of_instances: 1
instantiation_level_2:
number_of_instances: 3
targets: [ VDU1 ]
_EOF_
VNF 包的压缩
CSAR パッケージはアップロード用に zip ファイルに圧縮する必要があります。
cd ~/work/deployment
zip deployment.zip -r Definitions/ Files/ TOSCA-Metadata/
VNF パッケージの作成とアップロード
Tacker で空の VNF パッケージオブジェクトを作成し、作成した圧縮 VNF パッケージをアップロードします。
创建 VNF 包
空の VNF パッケージを作成します。
VNF パッケージが正常に作成されると、ID、リンク、オンボーディング状態、運用状態、使用状態などの情報が返されます。
$ openstack vnf package create
+-------------------+-------------------------------------------------------------------------------------------------+
| Field | Value |
+-------------------+-------------------------------------------------------------------------------------------------+
| ID | d765618d-a455-4fc5-99e2-ab457d34f92c |
| Links | { |
| | "self": { |
| | "href": "/vnfpkgm/v1/vnf_packages/d765618d-a455-4fc5-99e2-ab457d34f92c" |
| | }, |
| | "packageContent": { |
| | "href": "/vnfpkgm/v1/vnf_packages/d765618d-a455-4fc5-99e2-ab457d34f92c/package_content" |
| | } |
| | } |
| Onboarding State | CREATED |
| Operational State | DISABLED |
| Usage State | NOT_IN_USE |
| User Defined Data | {} |
+-------------------+-------------------------------------------------------------------------------------------------+
VNF パッケージ ID を環境変数として登録します。
export VNF_PACKAGE_ID=d765618d-a455-4fc5-99e2-ab457d34f92c
确认。
如果是以下的状态,说明创建成功。
$ openstack vnf package show $VNF_PACKAGE_ID \
-c 'Onboarding State' -c 'Operational State' -c 'Usage State'
+-------------------+------------+
| Field | Value |
+-------------------+------------+
| Onboarding State | CREATED |
| Operational State | DISABLED |
| Usage State | NOT_IN_USE |
+-------------------+------------+
VNF パッケージをアップロード
[VNF パッケージの圧縮] で作成した zip ファイルを作成した空の VNF パッケージにアップロードします。
cd ~/work/deployment
$ openstack vnf package upload --path deployment.zip $VNF_PACKAGE_ID
Upload request for VNF package 082f732d-4cb3-474b-8be0-cdace3224c6f has been accepted.
確認します。
下記の状態であれば問題ありません。
$ openstack vnf package show $VNF_PACKAGE_ID \
-c 'Onboarding State' -c 'Operational State' -c 'Usage State' -c 'VNFD ID'
+-------------------+--------------------------------------+
| Field | Value |
+-------------------+--------------------------------------+
| Onboarding State | ONBOARDED |
| Operational State | ENABLED |
| Usage State | NOT_IN_USE |
| VNFD ID | b1bb0ce7-ebca-4fa7-95ed-4840d7000003 |
+-------------------+--------------------------------------+
VNFD ID を環境変数として登録します。
export VNFD_ID=b1bb0ce7-ebca-4fa7-95ed-4840d7000003
制作CNF文件
创建一个CNF文件。
default VIM が設定されていない場合、下記のように未定義のエラーが出てしまうため、設定します。
$ openstack vnflcm create $VNFD_ID
Default VIM is not defined.
$ openstack vim set --is-default True $VIM_ID
default VIM が設定されている場合は下記のように実行結果が表示されます。
$ openstack vnflcm create $VNFD_ID
+-----------------------------+------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-----------------------------+------------------------------------------------------------------------------------------------------------------+
| ID | 952a2324-0ea5-4831-af87-4d9549f7b35a |
| Instantiation State | NOT_INSTANTIATED |
| Links | { |
| | "self": { |
| | "href": "http://localhost:9890/vnflcm/v1/vnf_instances/952a2324-0ea5-4831-af87-4d9549f7b35a" |
| | }, |
| | "instantiate": { |
| | "href": "http://localhost:9890/vnflcm/v1/vnf_instances/952a2324-0ea5-4831-af87-4d9549f7b35a/instantiate" |
| | } |
| | } |
| VNF Configurable Properties | |
| VNF Instance Description | None |
| VNF Instance Name | vnf-952a2324-0ea5-4831-af87-4d9549f7b35a |
| VNF Product Name | Sample VNF |
| VNF Provider | Company |
| VNF Software Version | 1.0 |
| VNFD ID | b1bb0ce7-ebca-4fa7-95ed-4840d7000003 |
| VNFD Version | 1.0 |
| vnfPkgId | |
+-----------------------------+------------------------------------------------------------------------------------------------------------------+
我们将VNF实例ID定义为环境变量。
export VNF_INSTANCE_ID=952a2324-0ea5-4831-af87-4d9549f7b35a
确认了。
$ openstack vnf package show $VNF_PACKAGE_ID \
-c 'Usage State'
+-------------+--------+
| Field | Value |
+-------------+--------+
| Usage State | IN_USE |
+-------------+--------+
$ openstack vnflcm show $VNF_INSTANCE_ID \
-c 'Instantiation State'
+---------------------+------------------+
| Field | Value |
+---------------------+------------------+
| Instantiation State | NOT_INSTANTIATED |
+---------------------+------------------+
将CNF实例化
实例化CNF。
创建请求参数文件
获取必要的信息,并创建实例请求所需的参数文件。
- vimConnectionInfo.vimId: e31459a6-1380-4fd8-930b-a70dc0500614
CNF をインスタンス化する VIM の ID を openstack vim list コマンドで取得します。
このコマンドで複数の VIM が出力された場合は自身が使用したい VIM の ID を 1 つ選択してください。
今回は新たに登録した Kubernetes を指定するため、test-vim-k8s-kubeadm の ID を選択します。
$ openstack vim list
+--------------------------------------+----------------------+----------------------------------+------------+------------+-----------+
| ID | Name | Tenant_id | Type | Is Default | Status |
+--------------------------------------+----------------------+----------------------------------+------------+------------+-----------+
| e31459a6-1380-4fd8-930b-a70dc0500614 | test-vim-k8s-kubeadm | cd492cafc33c4d6b878ee570f6aeae21 | kubernetes | False | REACHABLE |
+--------------------------------------+----------------------+----------------------------------+------------+------------+-----------+
创建请求参数文件。
additionalParams中包含了Kubernetes资源定义文件的路径。
请注意lcm-kubernetes-def-files必须是一个列表。
用户也可以指定需要部署资源的命名空间。
cat << _EOF_ > ~/work/instance_kubernetes.json
{
"flavourId": "simple",
"additionalParams": {
"lcm-kubernetes-def-files": [
"Files/kubernetes/deployment.yaml"
],
"namespace": "default"
},
"vimConnectionInfo": [
{
"id": "8a3adb69-0784-43c7-833e-aab0b6ab4470",
"vimId": "e31459a6-1380-4fd8-930b-a70dc0500614",
"vimType": "kubernetes"
}
]
}
_EOF_
创建实例
实例化 CNF 实例。
$ openstack vnflcm instantiate $VNF_INSTANCE_ID instance_kubernetes.json
Instantiate request for VNF Instance 952a2324-0ea5-4831-af87-4d9549f7b35a has been accepted.
确实。
如果实例化状态为”INSTANTIATED”,则表示实例化已成功。
$ openstack vnflcm show $VNF_INSTANCE_ID -c 'Instantiation State'
+---------------------+--------------+
| Field | Value |
+---------------------+--------------+
| Instantiation State | INSTANTIATED |
+---------------------+--------------+
如果NOT_INSTANTIATED没有改变,您也可以使用openstack vnflcm op list等命令来确认进展。
如果操作状态为PROCESSING,表示正在处理中。
确认 Kubernetes 的部署
确保在目标的Kubernetes VIM环境中运行着容器化的CNF。
此命令在Kubernetes主节点上执行。
如果 READY 是1/1,则表示部署已成功创建。
你也可以通过添加 -A 选项来确认它在哪个命名空间上运行。
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
curry-probe-test001 1/1 1 1 2m28s
$ kubectl get deployment -A
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
calico-apiserver calico-apiserver 2/2 2 2 97m
calico-system calico-kube-controllers 1/1 1 1 101m
calico-system calico-typha 1/1 1 1 101m
default curry-probe-test001 1/1 1 1 2m37s
default nginx-deployment 2/2 2 2 94m
kube-system coredns 2/2 2 2 120m
tigera-operator tigera-operator 1/1 1 1 102m
发生的错误 de
CNF 实例化失败。
这是在执行以下命令时发生的错误。
这个错误是在安装Devstack时,同时安装的Kubernetes作为VIM时发生的错误。
$ openstack vnflcm instantiate $VNF_INSTANCE_ID instance_kubernetes.json
创建资源失败
tacker-conductor[1171]: : kubernetes.client.exceptions.ApiException: (409)
tacker-conductor[1171]: 2022-07-13 01:12:51.559 ERROR tacker.vnflcm.vnflcm_driver [req-3a222d79-e537-4cb1-8722-33c1127deae8 admin admin] Unable to instantiate vnf instance f30d5550-99f4-45f5-93b9-8c84e0c56a2d due to error : Failed to create resource.: tacker.common.exceptions.CreateApiFalse: Failed to create resource.
tacker-conductor[1171]: 2022-07-13 01:12:51.560 ERROR root [req-3a222d79-e537-4cb1-8722-33c1127deae8 admin admin] Original exception being dropped: ['Traceback (most recent call last):\n', ' File "/opt/stack/tacker/tacker/vnfm/infra_drivers/kubernetes/k8s/translate_outputs.py", line 473, in deploy_k8s\n self._select_k8s_client_and_api(\n', ' File "/opt/stack/tacker/tacker/vnfm/infra_drivers/kubernetes/k8s/translate_outputs.py", line 400, in _select_k8s_client_and_api\n response = getattr(k8s_client_obj, self.method_value.get(kind))(\n', ' File "/usr/local/lib/python3.8/dist-packages/kubernetes/client/api/apps_v1_api.py", line 342, in create_namespaced_deployment\n return self.create_namespaced_deployment_with_http_info(namespace, body, **kwargs) # noqa: E501\n', ' File "/usr/local/lib/python3.8/dist-packages/kubernetes/client/api/apps_v1_api.py", line 437, in create_namespaced_deployment_with_http_info\n return self.api_client.call_api(\n', ' File "/usr/local/lib/python3.8/dist-packages/kubernetes/client/api_client.py", line 348, in call_api\n return self.__call_api(resource_path, method,\n', ' File "/usr/local/lib/python3.8/dist-packages/kubernetes/client/api_client.py", line 180, in __call_api\n response_data = self.request(\n', ' File "/usr/local/lib/python3.8/dist-packages/kubernetes/client/api_client.py", line 391, in request\n return self.rest_client.POST(url,\n', ' File "/usr/local/lib/python3.8/dist-packages/kubernetes/client/rest.py", line 275, in POST\n return self.request("POST", url,\n', ' File "/usr/local/lib/python3.8/dist-packages/kubernetes/client/rest.py", line 234, in request\n raise ApiException(http_resp=r)\n', 'kubernetes.client.exceptions.ApiException: (409)\nReason: Conflict\nHTTP response headers: HTTPHeaderDict({\'Audit-Id\': \'f779dfd4-2b9f-4745-9b0b-77e3c4a027e3\', \'Cache-Control\': \'no-cache, private\', \'Content-Type\': \'application/json\', \'X-Kubernetes-Pf-Flowschema-Uid\': \'278f6e23-4a3c-407d-a8d8-5865a79d827d\', \'X-Kubernetes-Pf-Prioritylevel-Uid\': \'109eaedd-4f4b-4c19-bd08-cc1a9c775c05\', \'Date\': \'Wed, 13
Content-Length\': \'250\'})\nHTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"deployments.apps \\"curry-probe-test001\\" already exists","reason":"AlreadyExists","details":{"name":"curry-probe-test001","group":"apps","kind":"deployments"},"code":409}\n\n\n', '\nDuring handling of the above exception, another exception occurred:\n\n', 'Traceback (most recent call last):\n', ' File "/opt/stack/tacker/tacker/vnflcm/vnflcm_driver.py", line 371, in _instantiate_vnf\n instance_id = self._vnf_manager.invoke(\n', ' File "/opt/stack/tacker/tacker/common/driver_manager.py", line 71, in invoke\n return getattr(driver, method_name)(**kwargs)\n', ' File "/opt/stack/tacker/tacker/vnfm/infra_drivers/kubernetes/kubernetes_driver.py", line 1837, in instantiate_vnf\n k8s_objs = transformer.deploy_k8s(k8s_objs)\n', ' File "/opt/stack/tacker/tacker/vnfm/infra_drivers/kubernetes/k8s/translate_outputs.py", line 494, in deploy_k8s\n raise exceptions.CreateApiFalse(error=msg)\n', 'tacker.common.exceptions.CreateApiFalse: Failed to create resource.\n']: tacker.common.exceptions.VnfInstantiationFailed: Vnf instantiation failed for vnf f30d5550-99f4-45f5-93b9-8c84e0c56a2d, error: Failed to create resource.
tacker-conductor[1171]: 2022-07-13 01:12:51.560 DEBUG tacker.common.log [req-3a222d79-e537-4cb1-8722-33c1127deae8 admin admin] tacker.conductor.conductor_server.Conductor method _change_vnf_status called with arguments (<tacker.context.Context object at 0x7fb5d4844a90>, 'f30d5550-99f4-45f5-93b9-8c84e0c56a2d', ('ACTIVE', 'INACTIVE', 'ERROR', 'PENDING_INSTANTIATE', 'PENDING_CREATE', 'PENDING_UPDATE', 'PENDING_DELETE', 'PENDING_SCALE_IN', 'PENDING_SCALE_OUT', 'PENDING_HEAL', 'PENDING_TERMINATE', 'PENDING_CHANGE_EXT_CONN'), 'ERROR') {} from (pid=1171) wrapper /opt/stack/tacker/tacker/common/log.py:33
tacker-conductor[1171]: 2022-07-13 01:12:51.563 DEBUG tacker.conductor.conductor_server [req-3a222d79-e537-4cb1-8722-33c1127deae8 admin admin] Change status of vnf f30d5550-99f4-45f5-93b9-8c84e0c56a2d from PENDING_CREATE to ERROR from (pid=1171) _change_vnf_status /opt/stack/tacker/tacker/conductor/conductor_server.py:643
无法创建资源。虽然我不太清楚原因,但在Kubernetes中似乎无法正常启动Pod。
我会检查VNF包中的清单文件和Kubernetes是否存在问题。
Kubernetes磁盘压力导致无法调度。
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
curry-probe-test001-766bdd79bf-jwmlf 0/2 Pending 0 19h <none> <none> <none> <none>
$ kubectl get node
NAME STATUS ROLES AGE VERSION
yoshitest2 Ready <none> 5d23h v1.22.3
$ kubectl describe node yoshitest2
Name: yoshitest2
Roles: <none>
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=yoshitest2
kubernetes.io/os=linux
Annotations: node.alpha.kubernetes.io/ttl: 0
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Thu, 07 Jul 2022 02:26:46 +0000
Taints: node.kubernetes.io/disk-pressure:NoSchedule
Unschedulable: false
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning EvictionThresholdMet 11m (x20720 over 2d11h) kubelet Attempting to reclaim ephemeral-storage
Warning FreeDiskSpaceFailed 83s (x718 over 2d11h) kubelet (combined from similar events): failed to garbage collect required amount of images. Wanted to free 8139422924 bytes, but freed 0 bytes
$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
default curry-probe-test001-766bdd79bf-jwmlf 0/2 Pending 0 19h
kube-system kube-apiserver-yoshitest2 1/1 Running 1 (5d23h ago) 5d23h
kube-system kube-controller-manager-yoshitest2 1/1 Running 1 (5d23h ago) 5d23h
kube-system kube-scheduler-yoshitest2 1/1 Running 1 (5d23h ago) 5d23h
查看节点(Node)和 Pod 的描述(Describe)得到了如上所示的结果。
- 参考: Master NodeにPodをデプロイするための設定
node.kubernetes.io/disk-pressure は Node のディスクが不足している場合に発生します。
そのため、ディスクの使用状況を確認します。
$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 7.8G 0 7.8G 0% /dev
tmpfs 1.6G 2.1M 1.6G 1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv 39G 37G 40M 100% /
tmpfs 7.9G 20K 7.9G 1% /dev/shm
...
通过确认,我们发现使用率已经达到了100%。
作为响应措施,我们暂时关闭了一次机器,并在ESXi上将磁盘分配增加了一倍。
网络插件 CNI 无法拆除 pod。
这是在扩展虚拟机磁盘并重新实例化时发生的错误。
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
curry-probe-test001-766bdd79bf-jwmlf 0/2 ContainerCreating 0 22h <none> yoshitest2 <none> <none>
curry-probe-test001-766bdd79bf-xfgnf 0/2 ContainerCreating 0 58m <none> yoshitest2 <none> <none>
$ kubectl describe pod curry-probe-test001-766bdd79bf-jwmlf
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 158m (x1186 over 22h) default-scheduler 0/1 nodes are available: 1 node(s) had taint {node.kubernetes.io/disk-pressure: }, that the pod didn't tolerate.
Normal Scheduled 59m default-scheduler Successfully assigned default/curry-probe-test001-766bdd79bf-jwmlf to yoshitest2
Warning Evicted 56m (x5 over 59m) kubelet The node was low on resource: ephemeral-storage.
Warning ExceededGracePeriod 29m (x46 over 59m) kubelet Container runtime did not kill the pod within specified grace period.
Warning FailedKillPod 4m11s (x286 over 59m) kubelet error killing pod: failed to "KillPodSandbox" for "c17d2b89-7786-46d6-a005-7e866347517f" with KillPodSandboxError: "rpc error: code = Unknown desc = networkPlugin cni failed to teardown pod \"curry-probe-test001-766bdd79bf-jwmlf_default\" network: Looks like http://localhost:5036/delNetwork cannot be reached. Is kuryr-daemon running?; Post \"http://localhost:5036/delNetwork\": dial tcp 127.0.0.1:5036: connect: connection refused"
Is kuryr-daemon running? となっており、kuryr-daemon が動作している? と書かれています。
また、localhost:5036/delNetwork cannot be reached より、通信ができていないようです。
通常、Devstack インストールの stack.sh 実行時完了に kuryr-daemon は動作しているはずですが、動作していません。
現状態から kuryr-kubernetes を動作させるためのコマンドを実行し、動作するかを試します。
実行コマンドは正常に kuryr-kubernetes が動作している環境にて ps コマンドを使用して調べました。
$ /usr/bin/python3 /usr/local/bin/kuryr-k8s-controller --config-dir /etc/kuryr
INFO kuryr_kubernetes.config [-] Logging enabled!
INFO kuryr_kubernetes.config [-] /usr/local/bin/kuryr-k8s-controller version 6.0.1
CRITICAL kuryr-kubernetes [-] Unhandled error: KeyError: 'KUBERNETES_SERVICE_HOST'
ERROR kuryr-kubernetes Traceback (most recent call last):
ERROR kuryr-kubernetes File "/usr/local/bin/kuryr-k8s-controller", line 10, in <module>
ERROR kuryr-kubernetes sys.exit(start())
ERROR kuryr-kubernetes File "/opt/stack/kuryr-kubernetes/kuryr_kubernetes/controller/service.py", line 180, in start
ERROR kuryr-kubernetes clients.setup_clients()
ERROR kuryr-kubernetes File "/opt/stack/kuryr-kubernetes/kuryr_kubernetes/clients.py", line 62, in setup_clients
ERROR kuryr-kubernetes setup_kubernetes_client()
ERROR kuryr-kubernetes File "/opt/stack/kuryr-kubernetes/kuryr_kubernetes/clients.py", line 72, in setup_kubernetes_client
ERROR kuryr-kubernetes host = os.environ['KUBERNETES_SERVICE_HOST']
ERROR kuryr-kubernetes File "/usr/lib/python3.8/os.py", line 675, in __getitem__
ERROR kuryr-kubernetes raise KeyError(key) from None
ERROR kuryr-kubernetes KeyError: 'KUBERNETES_SERVICE_HOST'
Unhandled error: KeyError: ‘KUBERNETES_SERVICE_HOST’ となっています。
KUBERNETES_SERVICE_HOST とは API を利用するための外向きのアドレスです。
.kube/config にこの情報が記録されています。
同様に KUBERNETES_SERVICE_PORT_HTTPS も設定しなければ同様のエラーが発生するため、定義します。
$ export KUBERNETES_SERVICE_HOST=10.100.2.220
$ export KUBERNETES_SERVICE_PORT_HTTPS=6443
定义后,再次执行命令。
$ /usr/bin/python3 /usr/local/bin/kuryr-k8s-controller --config-dir /etc/kuryr
INFO kuryr_kubernetes.config [-] Logging enabled!
INFO kuryr_kubernetes.config [-] /usr/local/bin/kuryr-k8s-controller version 6.0.1
CRITICAL kuryr-kubernetes [-] Unhandled error: RuntimeError: Unable to find token_file : /var/run/secrets/kubernetes.io/serviceaccount/token
ERROR kuryr-kubernetes Traceback (most recent call last):
ERROR kuryr-kubernetes File "/usr/local/bin/kuryr-k8s-controller", line 10, in <module>
ERROR kuryr-kubernetes sys.exit(start())
ERROR kuryr-kubernetes File "/opt/stack/kuryr-kubernetes/kuryr_kubernetes/controller/service.py", line 180, in start
ERROR kuryr-kubernetes clients.setup_clients()
ERROR kuryr-kubernetes File "/opt/stack/kuryr-kubernetes/kuryr_kubernetes/clients.py", line 62, in setup_clients
ERROR kuryr-kubernetes setup_kubernetes_client()
ERROR kuryr-kubernetes File "/opt/stack/kuryr-kubernetes/kuryr_kubernetes/clients.py", line 82, in setup_kubernetes_client
ERROR kuryr-kubernetes _clients[_KUBERNETES_CLIENT] = k8s_client.K8sClient(api_root)
ERROR kuryr-kubernetes File "/opt/stack/kuryr-kubernetes/kuryr_kubernetes/k8s_client.py", line 66, in __init__
ERROR kuryr-kubernetes raise RuntimeError(
ERROR kuryr-kubernetes RuntimeError: Unable to find token_file : /var/run/secrets/kubernetes.io/serviceaccount/token
正常な環境であれば /var/run/secrets/kubernetes.io/serviceaccount/ があるそうですが、エラーが発生している本環境では /var/run までしかありませんでした。
次に kuryr-kubernetes 系のサービスが復活できるかを試しました。
下記のサイトで Kuryr サービスが Kubernetes network アドオンとしてインストールされていることがわかりました。
- 参考: Kuryr installation as a Kubernetes network addon
似乎在stack.sh中使用以下命令安装kuryr-kubernetes。
在stack.sh中似乎使用了以下命令来安装kuryr-kubernetes。
在stack.sh脚本中好像使用了以下命令来安装kuryr-kubernetes。
source /opt/stack/kuryr-kubernetes/devstack/plugin.sh stack pre-install
source /opt/stack/kuryr-kubernetes/devstack/plugin.sh stack install
source /opt/stack/kuryr-kubernetes/devstack/plugin.sh stack post-config
source /opt/stack/kuryr-kubernetes/devstack/plugin.sh stack extra
source /opt/stack/kuryr-kubernetes/devstack/plugin.sh stack test-config
上記のコマンド実行しましたが、$DEST などの様々な環境変数が解決できず、not found エラーが発生しました。
在DevStack中,提供了一个名为unstack.sh的卸载脚本。此外,还提供了一个名为clean.sh的脚本,用于完全删除包括本地仓库在内的所有内容。在执行了这两个脚本之后,我重新执行了stack.sh。
$ ./unstack.sh
$ ./clean.sh
$ ./stack.sh
...
[Call Trace]
./stack.sh:1282:start_ovn_services
/opt/stack/devstack/lib/neutron-legacy:519:start_ovn
/opt/stack/devstack/lib/neutron_plugins/ovn_agent:700:wait_for_sock_file
/opt/stack/devstack/lib/neutron_plugins/ovn_agent:178:die
[ERROR] /opt/stack/devstack/lib/neutron_plugins/ovn_agent:178 Socket /var/run/openvswitch/ovnnb_db.sock not found
Error on exit
unstack.sh と clean.sh では初回インストール時に設定されたネットワークの設定が削除されません。
そのため、2 回目以降のインストール時に不整合が生じ、エラーとなっているようです。
対応として、環境を作成し直し、再度 stack.sh スクリプトを実行します。
最终, kuryr-kubernetes 无法正常运行。
stack@yoshitest:~/devstack$ kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system kube-apiserver-yoshitest 1/1 Running 1 (3m26s ago) 28s
kube-system kube-controller-manager-yoshitest 1/1 Running 1 (3m26s ago) 51s
kube-system kube-scheduler-yoshitest 1/1 Running 1 (3m26s ago) 50s
stack@yoshitest:~/devstack$ ps aux |grep kuryr
stack 14446 0.0 0.0 6384 2472 pts/0 S+ 07:33 0:00 grep --color=auto kuryr
docker images コマンドで Docker イメージがプルされていることは確認できました。
しかし、docker ps コマンドで確認すると、起動している様子はありませんでした。
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
kuryr/cni latest d5eef84bb247 2 hours ago 1.28GB
<none> <none> 29ba6174d4c5 2 hours ago 883MB
kuryr/controller latest d0868ab345af 2 hours ago 1.06GB
k8s.gcr.io/kube-apiserver v1.22.12 d922296a8b85 17 hours ago 128MB
k8s.gcr.io/kube-scheduler v1.22.12 5ee90014579c 17 hours ago 52.7MB
k8s.gcr.io/kube-controller-manager v1.22.12 f5ef4d6e36ee 17 hours ago 122MB
k8s.gcr.io/kube-proxy v1.22.12 761817698b62 17 hours ago 104MB
quay.io/centos/centos stream8 f8a44dfb7278 4 weeks ago 339MB
k8s.gcr.io/etcd 3.5.0-0 004811815584 13 months ago 295MB
k8s.gcr.io/coredns/coredns v1.8.4 8d147537fb7d 13 months ago 47.6MB
quay.io/kuryr/golang 1.16 d5dc529b0ee7 14 months ago 862MB
k8s.gcr.io/pause 3.5 ed210e3e4a5b 16 months ago 683kB
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
728597d87b27 k8s.gcr.io/pause:3.5 "/pause" 10 minutes ago Exited (0) 10 minutes ago k8s_POD_nginx-deployment-66b6c48dd5-pdlws_default_e2c38d0e-6dbf-40fd-8c9a-c6a5a5b17514_0
ad3c146a8c38 k8s.gcr.io/pause:3.5 "/pause" 10 minutes ago Exited (0) 10 minutes ago k8s_POD_nginx-deployment-66b6c48dd5-msvcp_default_3ec4a739-b003-4420-928d-09ceeab5c3ba_0
8e465e2810ab 5ee90014579c "kube-scheduler --au…" 37 minutes ago Up 37 minutes k8s_kube-scheduler_kube-scheduler-yoshitest_kube-system_acb57d0b7dff68b61cfe45619134da6c_1
e6bddd398239 d922296a8b85 "kube-apiserver --ad…" 37 minutes ago Up 37 minutes k8s_kube-apiserver_kube-apiserver-yoshitest_kube-system_83bd29bbe6554e93295c44ac4a1ffb04_1
a14ae872f42d f5ef4d6e36ee "kube-controller-man…" 37 minutes ago Up 37 minutes k8s_kube-controller-manager_kube-controller-manager-yoshitest_kube-system_badbf50c21b4819f89f3693e164f4804_1
6d50fd7b9147 k8s.gcr.io/pause:3.5 "/pause" 37 minutes ago Up 37 minutes k8s_POD_kube-controller-manager-yoshitest_kube-system_badbf50c21b4819f89f3693e164f4804_1
0fb02e37c808 k8s.gcr.io/pause:3.5 "/pause" 37 minutes ago Up 37 minutes k8s_POD_kube-apiserver-yoshitest_kube-system_83bd29bbe6554e93295c44ac4a1ffb04_1
008e41fb4f9b k8s.gcr.io/pause:3.5 "/pause" 37 minutes ago Up 37 minutes k8s_POD_kube-scheduler-yoshitest_kube-system_acb57d0b7dff68b61cfe45619134da6c_1
aa681ca00be7 f5ef4d6e36ee "kube-controller-man…" 2 hours ago Exited (255) 38 minutes ago k8s_kube-controller-manager_kube-controller-manager-yoshitest_kube-system_badbf50c21b4819f89f3693e164f4804_0
2b904fbf4145 5ee90014579c "kube-scheduler --au…" 2 hours ago Exited (255) 38 minutes ago k8s_kube-scheduler_kube-scheduler-yoshitest_kube-system_acb57d0b7dff68b61cfe45619134da6c_0
1f8929b099c6 d922296a8b85 "kube-apiserver --ad…" 2 hours ago Exited (255) 38 minutes ago k8s_kube-apiserver_kube-apiserver-yoshitest_kube-system_83bd29bbe6554e93295c44ac4a1ffb04_0
9447e7c252f8 k8s.gcr.io/pause:3.5 "/pause" 2 hours ago Exited (255) 38 minutes ago k8s_POD_kube-scheduler-yoshitest_kube-system_acb57d0b7dff68b61cfe45619134da6c_0
ca6f69e6faf7 k8s.gcr.io/pause:3.5 "/pause" 2 hours ago Exited (255) 38 minutes ago k8s_POD_kube-controller-manager-yoshitest_kube-system_badbf50c21b4819f89f3693e164f4804_0
3abbfee59682 k8s.gcr.io/pause:3.5 "/pause" 2 hours ago Exited (255) 38 minutes ago k8s_POD_kube-apiserver-yoshitest_kube-system_83bd29bbe6554e93295c44ac4a1ffb04_0
在这个环境中,kuryr-kubernetes服务无法正常运行的原因尚不清楚。
kuryr-kubernetes是用于连接OpenStack和Kubernetes的Neutron网络的服务。
它在Devstack的Kubernetes中充当了CNI的角色。
因此,如果kuryr-kubernetes无法运行,将无法创建新的Pod。
Kubernetes は CNI として kuryr-kubernetes を使用する必要はなく、Calico などを使用できます。
しかし、Devstack の Kubernetes では kuryr-kubernetes プラグインをインストールしなければ Kubernetes がインストールされません。
そのため、別途 Kubernetes 環境を準備し、VIM として使用します。
3. インストール手順 のように kubeadm で Kubernetes をインストールし、VIM として登録して利用したところ VNF として Pod を立てることができました。
无法安装Kubernetes。
Kubernetes インストール時に発生したエラーです。
tcp 127.0.0.1:10248: connect: connection refused
以下是命令执行时的错误。
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16
我们没有记录这个环境的错误日志,但是在使用kubeadm进行Kubernetes重新安装时,出现了与[发生失败]错误类似的错误。
我們將檢查 Docker 環境的驅動程式。
$ docker info | grep Cgroup
Cgroup Driver: cgroupfs
Cgroup Version: 1
我会添加以下内容,并重新加载守护程序并重新启动docker.service。
$ vim /etc/docker/daemon.json
・・・
"exec-opts": ["native.cgroupdriver=systemd"],
・・・
$ systemctl daemon-reload
$ systemctl restart docker
$ docker info | grep Cgroup
Cgroup Driver: systemd
Cgroup Version: 1
在这种状态下,再次运行 “sudo kubeadm init –pod-network-cidr=10.244.0.0/16” 命令,成功完成。
起动失败的样本.yaml。
下記のコマンド実行時のエラーです。
kubectl apply -f sample.yaml
nginx-deployment-66b6c48dd5-glcrt は本環境で立ち上がった Pod を指定してください。
kubectl get pod コマンドで調べることができます。
$ kubectl describe pod nginx-deployment-66b6c48dd5-glcrt
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 1s (x3 over 2m44s) default-scheduler 0/1 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.
由于在Master节点上设置了 node-role.kubernetes.io/master:NoSchedule 的 Taints,因此无法部署Pod。
因此,需要去除此Taint信息。
$ kubectl describe node yoshitest
...
Taints: node-role.kubernetes.io/master:NoSchedule
污染情报将被删除。
kubectl taint nodes yoshitest node-role.kubernetes.io/master:NoSchedule-
node/master untainted
总结
由于Kuryr-Kubernetes在重新启动时无法正常工作,所以无法使用DevStack的Kubernetes。
据说如果使用Vagrant启动DevStack,它不会在重新启动或其他情况下停止,但由于我没有尝试过,所以不太清楚。
我也想试一试。
非常感谢您阅读到这里。