Setting Up an On-premise Kubernetes Cluster from Scratch

[Service]
Environment=”HTTP_PROXY=<proxy_url>”
Environment=”HTTPS_PROXY=<proxy_url>”
Environment=”NO_PROXY=<list_of_addresses_and_hosts>”
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml --node-ip=192.168.56.14"
systemctl daemon-reload
systemctl restart kubelet
kubeadm config print init-defaults --component-configs=KubeletConfiguration > init.yaml
apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.56.12
bindPort: 6443
nodeRegistration:
criSocket: /run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
name: <whatever_identifier_you_want_for_this_node>
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: <any_cluster_name>
controllerManager: {}
controlPlaneEndpoint: "192.168.56.11:6443"
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: 1.22.0
networking:
dnsDomain: cluster.local
podSubnet: <reasonably_sized_private_subnet>
serviceSubnet: 10.96.0.0/12
scheduler: {}
---
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous:
enabled: false
webhook:
cacheTTL: 0s
enabled: true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 0s
cacheUnauthorizedTTL: 0s
cgroupDriver: systemd
clusterDNS:
- 10.96.0.10
clusterDomain: <same_cluster_name_as_cluster_configuration>
...
sudo kubeadm init --config init.yaml --upload-certs
kubeadm config print join-defaults --component-configs=KubeletConfiguration > join.yaml
apiVersion: kubeadm.k8s.io/v1beta3
caCertPath: /etc/kubernetes/pki/ca.crt
discovery:
bootstrapToken:
apiServerEndpoint: 192.168.60.11:6443
caCertHashes:
- sha256:<cluster_ca_cert_sha256_hash>
token: <same_token_as_init.yaml>
unsafeSkipCAVerification: true
timeout: 5m0s
tlsBootstrapToken: <same_token_as_init.yaml>
kind: JoinConfiguration
nodeRegistration:
criSocket: /run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
name: <identifier_for_this_worker_node>
taints: null
---
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous:
enabled: false
webhook:
cacheTTL: 0s
enabled: true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 0s
cacheUnauthorizedTTL: 0s
cgroupDriver: systemd
clusterDNS:
- <same_as_init.yaml>
clusterDomain: <same_as_init.yaml>
...
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
kubeadm token create --config init.yaml
kubeadm token list
sudo kubeadm join --config join.yaml
kubeadm config print join-defaults --component-configs=KubeletConfiguration > join.yaml
controlPlane:
localApiEndpoint:
advertiseAddress: 192.168.56.13
bindPort: 6443
certificateKey: <control_plane_certificate_key>
sudo kubeadm --config init.yaml init phase upload-certs --upload-certs
sudo kubeadm --config=join.yaml join
kubectl get nodes
"ipam": {
"type": "calico-ipam",
"assign_ipv4": "true",
"ipv4_pools": ["192.168.72.0/21"]
}
kubectl apply -f calico.yaml
kubectl create namespace metallb-system
apiVersion: v1
kind: ConfigMap
metadata:
name: config
namespace: metallb-system
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.56.24/29
- 192.168.56.34-192.168.56.35
- name: no-auto-assign
protocol: layer2
auto-assign: false
addresses:
- 192.168.56.33/32
kubectl apply -f metallb.yaml
kubectl apply -f nginx-ingress-controller.yaml
apiVersion: v1
kind: Service
metadata:
name: test-app
spec:
ports:
- name: http
port: 80
targetPort: http
selector:
name: test-app
app: phpmyadmin
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-app
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: "/"
spec:
rules:
- http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: test-app
port:
name: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-app
spec:
selector:
matchLabels:
name: test-app
app: phpmyadmin
template:
metadata:
labels:
name: test-app
app: phpmyadmin
spec:
containers:
- name: phpmyadmin
image: phpmyadmin/phpmyadmin:5.1.1
env:
- name: PMA_ARBITRARY
value: "1"
ports:
- name: http
containerPort: 80
---
kubectl apply -f test.yaml
kubectl get ingress

Wrapping Up

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store