Mencipta kluster RKE2 daripada UI Rancher berfungsi, tetapi ia menyembunyikan lapan komponen yang bergantung antara satu sama lain. Apabila kluster tersangkut pada “waiting for agent to check in”, UI tidak memberitahu komponen mana yang salah.
Template ini menggantikan klik dengan satu arahan bagi setiap komponen, dengan satu soalan “kenapa” bagi setiap langkah, supaya apabila ia gagal, anda tahu di mana. Ia mencipta kluster tiga node HA (etcd, control plane dan worker pada setiap node) di atas VM OpenStack melalui node driver OpenStack Rancher. Disahkan terhadap RKE2 v1.34.6+rke2r3 dan Rancher 2.14.
(Prasyarat OpenStack untuk node driver ini dibincangkan dalam Provisioning RKE2 from Rancher? Prepare OpenStack First.)
Penafian. Nilai seperti nama domain, alamat IP, ID rangkaian dan ID pengguna di bawah ialah pemegang tempat. Gantikan dengan nilai anda.
insecure: truepada kelayakan OpenStack hanya sesuai untuk lab yang menggunakan sijil tandatangan sendiri.
Gambaran besar: lapan komponen
FASA 0 PREFLIGHT (gate): DNS · server-url · /cacerts · driver · quota/flavor
↓ jika gagal, JANGAN teruskan
1. TOKEN siapa kita di Rancher
2. NODE DRIVER Rancher tahu cara cakap dengan OpenStack
3. CREDENTIAL username dan kata laluan OpenStack
4. MACHINE CONFIG cara bina VM: flavor, image, network, SG
5. CLUSTER berapa node, apa role, versi K8s
↓ Rancher terjemah kepada objek
Cluster → MachineSet → Machine ×3 → OpenstackMachine ×3 → VM ×3
↓ cloud-init: trust CA → pasang rancher-system-agent → RKE2
node Ready · etcd 3/3
Masa yang realistik: VM ACTIVE sekitar 9 minit, agent dan plan sekitar 5 minit, pemasangan RKE2 sekitar 10 minit. Jumlah sekitar 25 minit. Jangan panik pada mesej “waiting for cluster agent to connect”.
Pembolehubah yang digunakan di bawah:
set -a; source ~/.env; set +a # source DULU
RANCHER_URL="https://rancher.example.lan"
RANCHER_IP="<rancher-ip>"
RES="--resolve rancher.example.lan:443:$RANCHER_IP"
Sebab “source dahulu”: fail
.envsaya juga mengandungiRANCHER_URLuntuk Rancher lama. Jika anda menetapkannya sebelumsource, nilainya ditimpa dan anda log masuk ke server yang salah.
Untuk mengelak mengulang blok log masuk, definisikan sekali:
rancher_token() {
curl -sk $RES "$RANCHER_URL/v3-public/localProviders/local?action=login" \
-H 'Content-Type: application/json' \
-d "{\"username\":\"admin\",\"password\":\"$RANCHER_ADMIN_PW\",\"responseType\":\"json\"}" \
| python3 -c "import json,sys; print(json.load(sys.stdin)['token'])"
}
Fasa 0: Preflight (gate)
Lulus semua dahulu, baru teruskan.
0.1 DNS mesti wujud pada server DNS yang sebenar.
nslookup rancher.example.lan <dns-server> # jangka: alamat Rancher
Jika NXDOMAIN, tambah Host Override pada router/firewall. /etc/hosts pada hos admin anda tidak membantu VM; VM menggunakan nameserver rangkaian.
0.2 server-url mesti ditetapkan:
TOK=$(rancher_token)
curl -sk $RES -H "Authorization: Bearer $TOK" "$RANCHER_URL/v3/settings/server-url" \
| python3 -c "import json,sys; print('server-url =', json.load(sys.stdin).get('value'))"
Jika kosong, cloud-init gagal dengan FATAL: $CATTLE_SERVER was not set. Tetapkan dengan PUT.
0.3 /cacerts: punca nombor satu kluster tergantung.
curl -sk $RES "$RANCHER_URL/cacerts" | wc -c # jangka: > 0 (saya: 1277)
Jika 0, agent tidak boleh mempercayai Rancher, jadi jangan teruskan. Sahkan puncanya:
kubectl -n cattle-system get deploy rancher \
-o jsonpath='{.spec.template.spec.containers[0].args}' | tr ' ' '\n' | grep cacerts
# jika keluar "--no-cacerts", itulah puncanya
Penyelesaiannya: cipta secret tls-ca dan tls-ca-additional daripada sijil CA anda, kemudian helm upgrade rancher ... --reuse-values --set privateCA=true --set additionalTrustedCAs=true. Ulang 0.3 sehingga ia memulangkan kandungan.
0.4 Node driver aktif:
curl -sk $RES -H "Authorization: Bearer $TOK" "$RANCHER_URL/v3/nodedrivers/openstack" \
| python3 -c "import json,sys; print('driver active =', json.load(sys.stdin).get('active'))"
0.5 Kuota dan flavor:
openstack limits show --absolute -c Name -c Value -f value | paste - - | grep -E "total_cores_used|total_instances_used"
openstack flavor list -c Name -c VCPUs -c RAM -c Disk -f value | grep rancher
# flavor: 4 vCPU / 8192 MB / disk 50, disk mesti >= 50
0.6 Tiada kluster tersangkut yang tinggal:
kubectl -n fleet-default get clusters.provisioning.cattle.io,machines --no-headers # kosong = bersih
Fasa 1: Token
TOK=$(rancher_token), dan sahkan ia keluar (echo "${TOK:0:12}..."). Jika KeyError: 'token', anda log masuk ke server yang salah. Semak RANCHER_URL.
Kenapa: setiap langkah selepas ini menggunakan token ini.
Fasa 2: Node driver
curl -sk $RES -X PUT "$RANCHER_URL/v3/nodedrivers/openstack" \
-H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"active":true}'
Kenapa: memberitahu Rancher “saya mahu guna OpenStack”. Tanpa ini ia tidak tahu menterjemah
OpenstackConfigkepada panggilan Nova dan Neutron.
Fasa 3: Cloud credential
Cari dahulu dan guna semula jika ada, untuk mengelak pendua:
CRED_ID=$(curl -sk $RES -H "Authorization: Bearer $TOK" "$RANCHER_URL/v3/cloudCredentials" \
| python3 -c "import json,sys
for c in json.load(sys.stdin).get('data',[]):
if c['name']=='openstack-rancher': print(c['id']); break")
echo "CRED_ID=$CRED_ID"
Jika kosong, cipta:
[ -z "$CRED_ID" ] && curl -sk $RES -X POST "$RANCHER_URL/v3/cloudCredentials" \
-H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d "{\"type\":\"cloudCredential\",\"name\":\"openstack-rancher\",
\"openstackcredentialConfig\":{
\"authUrl\":\"http://<keystone-vip>:5000/v3\",
\"username\":\"<rancher-user>\",\"password\":\"$OPENSTACK_PW\",
\"tenantName\":\"<project>\",\"domainName\":\"Default\",
\"region\":\"RegionOne\",\"endpointType\":\"publicURL\",\"insecure\":true}}"
ID yang dipulangkan berbentuk cattle-global-data:cc-xxxxx. Jika awalan tiada, tambahkannya.
Kenapa: Rancher memerlukan kelayakan OpenStack untuk membina VM. Gunakan project khusus, bukan
admin(least privilege).
Fasa 4: Machine config (OpenstackConfig)
Ini “resepi VM”.
CLUSTER_NAME="rancher-os-2"
MACHINE_CONFIG="nc-${CLUSTER_NAME}"
K8S_VERSION="v1.34.6+rke2r3"
cat > /tmp/nc.yaml <<YAML
apiVersion: rke-machine-config.cattle.io/v1
kind: OpenstackConfig
metadata:
name: ${MACHINE_CONFIG}
namespace: fleet-default
activeTimeout: "1200"
authUrl: http://<keystone-vip>:5000/v3
username: <rancher-user>
password: ${OPENSTACK_PW}
tenantName: <project>
domainName: Default
region: RegionOne
endpointType: publicURL
insecure: true
flavorName: rancher.node
imageName: ubuntu-24.04-cloud
netId: <network-id>
secGroups: rancher-sg
sshUser: ubuntu
sshPort: "22"
keypairName: ""
volumeSize: "0"
bootFromVolume: false
configDrive: true
YAML
kubectl apply --dry-run=server -f /tmp/nc.yaml # sahkan dahulu
kubectl apply -f /tmp/nc.yaml
Setiap medan di sini ada sebab:
| Medan | Nilai | Kenapa |
|---|---|---|
activeTimeout | 1200 | Lalai 200 s terlalu singkat; VM di atas Ceph HDD mengambil sekitar 9 minit |
flavorName | rancher.node | Disk 50 GB. disk=0 dengan imej kecil memberi root disk yang kecil |
netId | ID rangkaian | Medan ini sahaja. netName diabaikan oleh driver |
secGroups | nama SG | Nama, bukan ID |
sshUser | ubuntu | Lalai driver ialah root, yang tidak dibenarkan oleh imej Ubuntu |
keypairName | kosong | Jika diisi, privateKeyFile mesti diberi juga, jika tidak driver menolak |
volumeSize | 0 | Mengelak bug endpoint Cinder (502) |
bootFromVolume | false | Boot ke ephemeral, elak laluan Cinder |
configDrive | true | Wajib. DHCP pada rangkaian itu tidak berfungsi, jadi IP datang dari config drive |
Fasa 5: Kluster
Dapatkan ID pengguna semasa (diperlukan untuk anotasi pencipta):
ADMIN_UID=$(curl -sk $RES -H "Authorization: Bearer $TOK" "$RANCHER_URL/v3/tokens" \
| python3 -c "import json,sys
for t in json.load(sys.stdin).get('data',[]):
if t.get('current'): print(t.get('userId'))" | head -1)
Spesifikasi kluster:
cat > /tmp/cluster.json <<JSON
{
"apiVersion": "provisioning.cattle.io/v1",
"kind": "Cluster",
"metadata": {
"name": "${CLUSTER_NAME}", "namespace": "fleet-default",
"annotations": { "field.cattle.io/creatorId": "${ADMIN_UID}" }
},
"spec": {
"cloudCredentialSecretName": "${CRED_ID}",
"kubernetesVersion": "${K8S_VERSION}",
"rkeConfig": {
"machinePools": [{
"name": "cp", "quantity": 3,
"etcdRole": true, "controlPlaneRole": true, "workerRole": true,
"machineConfigRef": { "kind": "OpenstackConfig", "name": "${MACHINE_CONFIG}" },
"drainBeforeDelete": false, "nodeStartupTimeout": "20m"
}],
"upgradeStrategy": { "controlPlaneConcurrency": "1", "workerConcurrency": "10%" }
}
}
}
JSON
Sahkan tanpa mencipta (dryRun=All), kemudian cipta:
URL="$RANCHER_URL/apis/provisioning.cattle.io/v1/namespaces/fleet-default/clusters"
curl -sk $RES -X POST "$URL?dryRun=All" -H "Authorization: Bearer $TOK" \
-H 'Content-Type: application/json' --data-binary @/tmp/cluster.json -o /tmp/r.json -w "HTTP=%{http_code}\n"
# HTTP=201 = sah. HTTP=422 = mesej memberitahu medan mana yang salah
curl -sk $RES -X POST "$URL" -H "Authorization: Bearer $TOK" \
-H 'Content-Type: application/json' --data-binary @/tmp/cluster.json
Jangan guna
kubectl applyuntuk menciptaCluster. Webhook admission Rancher menolaknya dengancreatorID annotation does not match user, keranakubectlyang menuju ke API server Rancher datang sebagai sijil RKE2, bukan sebagai pengguna Rancher. Gunakan API seperti di atas.OpenstackConfigpula boleh dengankubectl: dua laluan berbeza.
Fasa 6 dan 7: Pantau
VM dibina:
watch -n 15 'openstack server list --all-projects -c Name -c Status -f value | grep rancher'
# jangka: 3 baris, BUILD → ACTIVE (sekitar 9 minit setiap satu)
Machine dan agent:
kubectl -n fleet-default get machines \
-o custom-columns='NAME:.metadata.name,PHASE:.status.phase' --no-headers # Provisioning → Running
kubectl -n fleet-default get clusters.provisioning.cattle.io -o json | python3 -c "
import json,sys
for i in json.load(sys.stdin).get('items',[]):
print('ready =', i.get('status',{}).get('ready'))
for c in i.get('status',{}).get('conditions',[]):
if c['type'] in ('Ready','Provisioned','Connected','Stalled'):
print(f\" {c['type']:<12} {c['status']:<8} {str(c.get('message') or '')[:75]}\")"
Bukti agent berjaya (kunci diagnosis): baca log konsol VM.
for VM in $(openstack server list --all-projects -c ID -c Name -f value | grep "$CLUSTER_NAME" | awk '{print $1}'); do
openstack console log show "$VM" | grep -iE \
"Successfully tested Rancher connection|CATTLE_SERVER was not set|Could not resolve host|FATAL" | sort -u
done
Tafsiran mesej kondisi:
| Mesej | Maksud | Jika tersekat lama |
|---|---|---|
waiting for infrastructure ready | VM masih dibina | Semak kuota dan FIP pool |
waiting for agent to check in | Agent belum melapor | CA, DNS atau server-url salah |
waiting for cluster agent to connect | Agent berjalan, RKE2 belum naik | Normal, sekitar 10 minit |
configuring etcd node(s) | etcd sedang terbentuk | Normal, hampir siap |
no etcd machines exist that have plans | Kluster tidak boleh pulih | Padam dan cipta semula (Fasa 9) |
Fasa 8: Sahkan siap dan ambil kubeconfig
# 8.1 kluster Ready?
kubectl -n fleet-default get clusters.provisioning.cattle.io \
-o custom-columns='NAME:.metadata.name,READY:.status.ready,K8S:.spec.kubernetesVersion' --no-headers
# 8.2 kubeconfig kluster baharu melalui proksi Rancher
CID=$(kubectl -n fleet-default get clusters.provisioning.cattle.io "$CLUSTER_NAME" -o jsonpath='{.status.clusterName}')
curl -sk $RES -X POST "$RANCHER_URL/v3/clusters/$CID?action=generateKubeconfig" \
-H "Authorization: Bearer $(rancher_token)" \
| python3 -c "import json,sys; print(json.load(sys.stdin)['config'])" > ~/kubeconfig-${CLUSTER_NAME}.yaml
chmod 600 ~/kubeconfig-${CLUSTER_NAME}.yaml
# 8.3 SAHKAN node dengan kubeconfig kluster BARU, bukan kubeconfig pengurusan
KUBECONFIG=~/kubeconfig-${CLUSTER_NAME}.yaml kubectl get nodes -o wide # jangka: 3 × Ready
Jika get nodes menyenaraikan node pengurusan Rancher, anda menggunakan kubeconfig yang salah.
8.4 Kuorum etcd. Imej etcd tiada sh, jadi jangan guna sh -c:
ETCD=$(KUBECONFIG=$KC kubectl -n kube-system get pods -o name | grep etcd | head -1)
KUBECONFIG=$KC kubectl -n kube-system exec "$ETCD" -- etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt \
--cert=/var/lib/rancher/rke2/server/tls/etcd/server-client.crt \
--key=/var/lib/rancher/rke2/server/tls/etcd/server-client.key member list -w table
# jangka: 3 baris "started"
KUBECONFIG=$KC kubectl get --raw='/readyz' # jangka: ok
Fasa 9: Buang kluster yang tersangkut
kubectl -n fleet-default delete clusters.provisioning.cattle.io "$CLUSTER_NAME" --wait=false
for i in $(seq 1 12); do
printf "[%d] mesin=%s cp=%s kluster=%s\n" "$i" \
"$(kubectl -n fleet-default get machines --no-headers 2>/dev/null | wc -l)" \
"$(kubectl -n fleet-default get rkecontrolplanes --no-headers 2>/dev/null | wc -l)" \
"$(kubectl -n fleet-default get clusters.provisioning.cattle.io --no-headers 2>/dev/null | wc -l)"
sleep 30
done
Jangan padam
rkecontrolplanesahaja. Finalizerrke-control-plane-removemenunggu machine dipadam, tetapimachinePools[].quantity: 3menyebabkan MachineSet mencipta mesin baru secepat anda memadamnya. Ia menjadi perlumbaan dan finalizer tidak akan selesai. Padam Cluster supaya pool berhenti, dan mesin akan dibuang mengikut urutan. (Kisah penuh: Unblocking a Rancher Cluster Stuck in ‘Deleting’.)
Jika VM yatim tinggal (machine sudah tiada tetapi VM masih hidup), senaraikan dan padam yang tiada CR Machine sepadan: openstack server delete <nama-vm>.
Urutan ringkas
Fasa 0 preflight → 5 gate: DNS · server-url · /cacerts · driver · quota/flavor
Fasa 1 token → log masuk, simpan $TOK
Fasa 2 driver → PUT /v3/nodedrivers/openstack {"active":true}
Fasa 3 credential → cari / guna semula
Fasa 4 machinecfg → kubectl apply nc-<nama>.yaml
Fasa 5 cluster → curl POST /apis/.../clusters (BUKAN kubectl)
Fasa 6 VM → BUILD → ACTIVE ~9 min
Fasa 7 agent → "Successfully tested Rancher connection"
Fasa 8 sahkan → kubectl get nodes (kubeconfig BARU) + etcdctl member list
Fasa 9 (kebal) → padam Cluster, JANGAN padam rkecontrolplane
Falsafah di sebalik semua ini: satu arahan, satu komponen, jangan lompat. Apabila kluster tersangkut, mesej kondisi pada Fasa 7 menyempitkan masalah kepada satu daripada tiga punca (CA, DNS atau server-url), dan Fasa 0 memastikan ketiga-tiganya sudah diperiksa sebelum VM pertama dibina.
Leave a Comment / Ask a Question
Have thoughts or questions on this article? Drop a message below and Faiez will receive an instant notification.