diff --git a/docs/02-client-tools.md b/docs/02-client-tools.md index 7e73cb3..88a9f27 100644 --- a/docs/02-client-tools.md +++ b/docs/02-client-tools.md @@ -157,15 +157,35 @@ Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.6", GitCom In your terminal, run the following to define a few shell helper functions that we'll use throughout the tutorial: ``` +function oci-fetch-public-ip(){ + # Helper function to fetch and stash the public IP for the given OCI compute instance + if [ -z "$1" ] + then + echo "Usage: oci-fetch-public-ip " + else + file=.kubernetes-the-hard-way/$1/public_ip + if [ ! -f "$file" ] || [ ! -s "$file" ]; + then + # Fetch the public IP and stash it for quick lookup by later commands + echo "Fetching $1 Public IP..." + mkdir -p .kubernetes-the-hard-way/$1 + ocid=$(oci compute instance list --lifecycle-state RUNNING --display-name $1 \ + | jq -r .data[0].id) + oci compute instance list-vnics --instance-id $ocid | jq -r '.data[0]["public-ip"]' \ + > .kubernetes-the-hard-way/$1/public_ip + fi + fi +} + function oci-ssh(){ # Helper function to ssh into a named OCI compute instance if [ -z "$1" ] then echo "Usage: oci-ssh " else - ocid=$(oci compute instance list --lifecycle-state RUNNING --display-name $1 | jq -r .data[0].id) - ip=$(oci compute instance list-vnics --instance-id $ocid | jq -r '.data[0]["public-ip"]') - ssh -i kubernetes_ssh_rsa ubuntu@$ip $2 + oci-fetch-public-ip $1 + public_ip=$(cat .kubernetes-the-hard-way/$1/public_ip) + ssh -i kubernetes_ssh_rsa ubuntu@$public_ip $2 fi } @@ -175,11 +195,17 @@ function oci-scp(){ then echo "Usage: oci-scp " else - ocid=$(oci compute instance list --lifecycle-state RUNNING --display-name ${@: (-2):1} | jq -r .data[0].id) - ip=$(oci compute instance list-vnics --instance-id $ocid | jq -r '.data[0]["public-ip"]') - scp -i kubernetes_ssh_rsa "${@:1:$#-2}" ubuntu@$ip:${@: -1} + oci-fetch-public-ip ${@: (-2):1} + public_ip=$(cat .kubernetes-the-hard-way/${@: (-2):1}/public_ip) + scp -i kubernetes_ssh_rsa "${@:1:$#-2}" ubuntu@$public_ip:${@: -1} fi } ``` +For convenience throughout the rest of this tutorial, you can copy the above functions into your shell's profile, to avoid having to redefine them in each of the various tmux terminals we'll create. For example, for Bash shell, copy and past the above functions into `~/.bashrc`, then refresh the profile from your current terminal session with: + +```` +. ~/.bashrc +``` + Next: [Provisioning Compute Resources](03-compute-resources.md) diff --git a/docs/03-compute-resources.md b/docs/03-compute-resources.md index b5d910d..0857669 100644 --- a/docs/03-compute-resources.md +++ b/docs/03-compute-resources.md @@ -17,7 +17,8 @@ In this section a dedicated [Virtual Cloud Network](https://www.oracle.com/cloud Create the `kubernetes-the-hard-way` custom VCN: ``` -VCN_ID=$(oci network vcn create --display-name kubernetes-the-hard-way --dns-label vcn --cidr-block 10.240.0.0/24 | jq -r .data.id) +VCN_ID=$(oci network vcn create --display-name kubernetes-the-hard-way --dns-label vcn --cidr-block \ + 10.240.0.0/24 | jq -r .data.id) ``` A [subnet](https://docs.oracle.com/en-us/iaas/Content/Network/Tasks/managingVCNs_topic-Overview_of_VCNs_and_Subnets.htm#Overview) must be provisioned with an IP address range large enough to assign a private IP address to each node in the Kubernetes cluster. @@ -25,11 +26,12 @@ A [subnet](https://docs.oracle.com/en-us/iaas/Content/Network/Tasks/managingVCNs Create the `kubernetes` subnet in the `kubernetes-the-hard-way` VCN, along with a Route Table and Internet Gateway allowing traffic to the internet. ``` -INTERNET_GATEWAY_ID=$(oci network internet-gateway create --vcn-id $VCN_ID --is-enabled true \ - --display-name kubernetes-the-hard-way | jq -r .data.id) -ROUTE_TABLE_ID=$(oci network route-table create --vcn-id $VCN_ID --display-name kubernetes-the-hard-way \ - --route-rules "[{\"cidrBlock\":\"0.0.0.0/0\",\"networkEntityId\":\"$INTERNET_GATEWAY_ID\"}]" | jq -r .data.id) -SUBNET_ID=$(oci network subnet create --display-name kubernetes --dns-label subnet --vcn-id $VCN_ID \ +INTERNET_GATEWAY_ID=$(oci network internet-gateway create --display-name kubernetes-the-hard-way \ + --vcn-id $VCN_ID --is-enabled true | jq -r .data.id) +ROUTE_TABLE_ID=$(oci network route-table create --display-name kubernetes-the-hard-way --vcn-id $VCN_ID \ + --route-rules "[{\"cidrBlock\":\"0.0.0.0/0\",\"networkEntityId\":\"$INTERNET_GATEWAY_ID\"}]" \ + | jq -r .data.id) +SUBNET_ID=$(oci network subnet create --display-name kubernetes --vcn-id $VCN_ID --dns-label subnet \ --cidr-block 10.240.0.0/24 --route-table-id $ROUTE_TABLE_ID | jq -r .data.id) ``` @@ -72,10 +74,11 @@ kubernetes_ssh_rsa.pub Create three compute instances which will host the Kubernetes control plane: ``` -IMAGE_ID=$(oci compute image list --operating-system "Canonical Ubuntu" --operating-system-version "20.04" | jq -r .data[0].id) +IMAGE_ID=$(oci compute image list --operating-system "Canonical Ubuntu" --operating-system-version \ + "20.04" | jq -r .data[0].id) +NUM_ADS=$(oci iam availability-domain list | jq -r .data | jq length) for i in 0 1 2; do - # Rudimentary spreading of nodes across Availability Domains and Fault Domains - NUM_ADS=$(oci iam availability-domain list | jq -r .data | jq length) + # Rudimentary distributing of nodes across Availability Domains and Fault Domains AD_NAME=$(oci iam availability-domain list | jq -r .data[$((i % NUM_ADS))].name) NUM_FDS=$(oci iam fault-domain list --availability-domain $AD_NAME | jq -r .data | jq length) FD_NAME=$(oci iam fault-domain list --availability-domain $AD_NAME | jq -r .data[$((i % NUM_FDS))].name) @@ -83,7 +86,8 @@ for i in 0 1 2; do oci compute instance launch --display-name controller-${i} --assign-public-ip true \ --subnet-id $SUBNET_ID --shape VM.Standard.E3.Flex --availability-domain $AD_NAME \ --fault-domain $FD_NAME --image-id $IMAGE_ID --shape-config '{"memoryInGBs": 8.0, "ocpus": 2.0}' \ - --private-ip 10.240.0.1${i} --freeform-tags \'{"project": "kubernetes-the-hard-way","role":"controller"}' \ + --private-ip 10.240.0.1${i} \ + --freeform-tags '{"project": "kubernetes-the-hard-way","role":"controller"}' \ --metadata "{\"ssh_authorized_keys\":\"$(cat kubernetes_ssh_rsa.pub)\"}" done ``` @@ -97,10 +101,11 @@ Each worker instance requires a pod subnet allocation from the Kubernetes cluste Create three compute instances which will host the Kubernetes worker nodes: ``` -IMAGE_ID=$(oci compute image list --operating-system "Canonical Ubuntu" --operating-system-version "20.04" | jq -r .data[0].id) +IMAGE_ID=$(oci compute image list --operating-system "Canonical Ubuntu" --operating-system-version \ + "20.04" | jq -r .data[0].id) +NUM_ADS=$(oci iam availability-domain list | jq -r .data | jq length) for i in 0 1 2; do - # Rudimentary spreading of nodes across Availability Domains and Fault Domains - NUM_ADS=$(oci iam availability-domain list | jq -r .data | jq length) + # Rudimentary distributing of nodes across Availability Domains and Fault Domains AD_NAME=$(oci iam availability-domain list | jq -r .data[$((i % NUM_ADS))].name) NUM_FDS=$(oci iam fault-domain list --availability-domain $AD_NAME | jq -r .data | jq length) FD_NAME=$(oci iam fault-domain list --availability-domain $AD_NAME | jq -r .data[$((i % NUM_FDS))].name) @@ -108,7 +113,8 @@ for i in 0 1 2; do oci compute instance launch --display-name worker-${i} --assign-public-ip true \ --subnet-id $SUBNET_ID --shape VM.Standard.E3.Flex --availability-domain $AD_NAME \ --fault-domain $FD_NAME --image-id $IMAGE_ID --shape-config '{"memoryInGBs": 8.0, "ocpus": 2.0}' \ - --private-ip 10.240.0.2${i} --freeform-tags '{"project": "kubernetes-the-hard-way","role":"worker"}' \ + --private-ip 10.240.0.2${i} \ + --freeform-tags '{"project": "kubernetes-the-hard-way","role":"worker"}' \ --metadata "{\"ssh_authorized_keys\":\"$(cat kubernetes_ssh_rsa.pub)\",\"pod-cidr\":\"10.200.${i}.0/24\"}" \ --skip-source-dest-check true done @@ -119,7 +125,8 @@ done List the compute instances in our compartment: ``` -oci compute instance list --sort-by DISPLAYNAME --lifecycle-state RUNNING --all | jq -r .data[] | jq '{"display-name","lifecycle-state"}' +oci compute instance list --sort-by DISPLAYNAME --lifecycle-state RUNNING --all | jq -r .data[] \ + | jq '{"display-name","lifecycle-state"}' ``` > output @@ -193,57 +200,65 @@ For use in later steps of the tutorial, we'll create Security Lists to allow: - Public access to the LoadBalancer port. ``` -INTRA_VCN_SECURITY_LIST_ID=$(oci network security-list create --vcn-id $VCN_ID --display-name intra-vcn --ingress-security-rules '[ { - "icmp-options": null, - "is-stateless": true, - "protocol": "all", - "source": "10.240.0.0/24", - "source-type": "CIDR_BLOCK", - "tcp-options": null, - "udp-options": null -}]' --egress-security-rules '[]' | jq -r .data.id) - -WORKER_SECURITY_LIST_ID=$(oci network security-list create --vcn-id $VCN_ID --display-name worker --ingress-security-rules '[ -{ - "icmp-options": null, - "is-stateless": false, - "protocol": "6", - "source": "0.0.0.0/0", - "source-type": "CIDR_BLOCK", - "tcp-options": { - "destination-port-range": { - "max": 32767, - "min": 30000 + INTRA_VCN_SECURITY_LIST_ID=$(oci network security-list create --display-name intra-vcn \ + --vcn-id $VCN_ID --ingress-security-rules '[ + { + "icmp-options": null, + "is-stateless": true, + "protocol": "all", + "source": "10.240.0.0/24", + "source-type": "CIDR_BLOCK", + "tcp-options": null, + "udp-options": null + }]' --egress-security-rules '[]' | jq -r .data.id) + + WORKER_SECURITY_LIST_ID=$(oci network security-list create --display-name worker \ + --vcn-id $VCN_ID --ingress-security-rules '[ + { + "icmp-options": null, + "is-stateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "source-type": "CIDR_BLOCK", + "tcp-options": { + "destination-port-range": { + "max": 32767, + "min": 30000 + }, + "source-port-range": null }, - "source-port-range": null - }, - "udp-options": null -}]' --egress-security-rules '[]' | jq -r .data.id) - -LB_SECURITY_LIST_ID=$(oci network security-list create --vcn-id $VCN_ID --display-name load-balancer --ingress-security-rules '[ -{ - "icmp-options": null, - "is-stateless": false, - "protocol": "6", - "source": "0.0.0.0/0", - "source-type": "CIDR_BLOCK", - "tcp-options": { - "destination-port-range": { - "max": 6443, - "min": 6443 + "udp-options": null + }]' --egress-security-rules '[]' | jq -r .data.id) + + LB_SECURITY_LIST_ID=$(oci network security-list create --display-name load-balancer \ + --vcn-id $VCN_ID --ingress-security-rules '[ + { + "icmp-options": null, + "is-stateless": false, + "protocol": "6", + "source": "0.0.0.0/0", + "source-type": "CIDR_BLOCK", + "tcp-options": { + "destination-port-range": { + "max": 6443, + "min": 6443 + }, + "source-port-range": null }, - "source-port-range": null - }, - "udp-options": null -}]' --egress-security-rules '[]' | jq -r .data.id) + "udp-options": null + }]' --egress-security-rules '[]' | jq -r .data.id) +} ``` We'll add these Security Lists to our subnet: ``` -DEFAULT_SECURITY_LIST_ID=$(oci network security-list list --display-name "Default Security List for kubernetes-the-hard-way" | jq -r .data[0].id) -oci network subnet update --subnet-id $SUBNET_ID --security-list-ids \ - "[\"$DEFAULT_SECURITY_LIST_ID\",\"$INTRA_VCN_SECURITY_LIST_ID\",\"$WORKER_SECURITY_LIST_ID\",\"$LB_SECURITY_LIST_ID\"]" --force +{ + DEFAULT_SECURITY_LIST_ID=$(oci network security-list list --display-name \ + "Default Security List for kubernetes-the-hard-way" | jq -r .data[0].id) + oci network subnet update --subnet-id $SUBNET_ID --force --security-list-ids \ + "[\"$DEFAULT_SECURITY_LIST_ID\",\"$INTRA_VCN_SECURITY_LIST_ID\",\"$WORKER_SECURITY_LIST_ID\",\"$LB_SECURITY_LIST_ID\"]" +} ``` ### Firewall Rules @@ -272,6 +287,7 @@ LOADBALANCER_ID=$(oci lb load-balancer create --display-name kubernetes-the-har Create a Backend Set, with Backends for the our 3 controller nodes: ``` +{ cat > backends.json < kubernetes-csr.json <