With Anthos clusters on bare metal, you can define four types of clusters:
- admin: a cluster used to manage user clusters
- user: a cluster used to run workloads
- standalone: a single cluster that can administer itself and run workloads, but that can't create or manage other user clusters
- hybrid: a single cluster for both admin and workloads that can also manage user clusters
In this quickstart, you deploy a two-node hybrid cluster with Anthos clusters on bare metal. You learn how to create a cluster and how to monitor the cluster creation process.
This quickstart assumes that you have a basic understanding of Kubernetes.
Prepare for Anthos clusters on bare metal
Anthos clusters on bare metal has an installation command called
bmctl designed to
streamline the creation of clusters. The
bmctl command can automatically set up
the necessary Google service accounts and APIs that you need for Anthos clusters on bare metal.
This quickstart uses those automatically generated service accounts, services, and APIs.
You can manually set up Google service accounts, services, and APIs
before you create clusters with
bmctl. This document shows the API command changes that you need. To set up the service accounts and services
that you need, go to
Enabling Google services and service accounts.
Before you can use Anthos clusters on bare metal to create a cluster, complete the following tasks:
- Create a Google Cloud project where your account has the Editor or Owner role.
- Download and install the
Configure a Linux admin workstation to run
- Install Docker version 19.03 or later. To learn how to configure Docker, go to the page corresponding to your Linux distribution:
- To use
rootaccess, set up SSH on both the admin workstation and the remote cluster node machines. Initially, you need
rootSSH password authentication enabled on the remote cluster node machines to share keys from the admin workstation. After the keys are in place, you can disable SSH password authentication.
Generate a private/public key pair on the admin workstation. Don't set a passphrase for the keys. You need the keys to use SSH for secure, passwordless connections between the admin workstation and the cluster node machines. Generate the keys with the following command:
ssh-keygen -t rsa
You can also use
SUDOuser access to the cluster node machines to set up SSH, but for passwordless, non-root user connections you need to update the cluster configuration file with the appropriate credentials. For more information, go to the
#Node access configurationsection in the sample cluster config file..
- Add the generated public key to the cluster node machines. By default,
the public keys are stored in the
ssh-copy-id -i ~/.ssh/IDENTITY_FILE root@CLUSTER_NODE_IP
- Disable SSH password authentication on the cluster node machines. Use the following command on the admin workstation to verify that public key authentication works between the admin workstation and the cluster node machines.
ssh -o IdentitiesOnly=yes -i IDENTITY_FILE root@CLUSTER_NODE_IP
Install gcloud utilities
kubectl tools are included in
the Cloud SDK.
- On your admin workstation, install and initialize the Cloud SDK by using
these instructions. This process installs
- Update the Cloud SDK:
gcloud components update
Log in with your Google Account to manage services and service accounts:
gcloud auth login --update-adc
A new browser tab opens and you are prompted to choose an account.
However, this quickstart shows you how to specify a project and set up the required Google services directly with the
bmctlcommand when you create your clusters. When you do these actions with
bmctl, it always uses the project ID that you specify in the command.
gcloud components install kubectl
You use the
bmctl command-line tool to create clusters in Anthos clusters on bare metal.
bmctl from a Cloud Storage bucket.
- Create a new directory for
bmctlfrom the Cloud Storage bucket:
gsutil cp gs://anthos-baremetal-release/bmctl/1.7.1/linux-amd64/bmctl bmctl
chmod a+x bmctl
- Ensure that
bmctlis installed correctly by viewing the help information:
Create your cluster nodes
Create two machines to serve as nodes for your cluster:
- One machine functions as the control plane node.
- One machine functions as the worker node.
Create a cluster
To create a cluster:
bmctlto create a config file.
- Edit the config file to customize it for your cluster and network.
bmctlto create the cluster from the config file.
Create a config file
To create a config file and enable service accounts and APIs automatically,
make sure that you are in the
baremetal directory, and issue
bmctl command with the following flags:
./bmctl create config -c CLUSTER_NAME \ --enable-apis --create-service-accounts --project-id=PROJECT_ID
CLUSTER_NAME with the name of your cluster. Replace
with the Google Cloud project that you want to use and where your account has an
Owner or Editor role.
The preceding command creates a config file under the
directory at the following path:
Edit the config file
To edit the config file:
- Open the
bmctl-workspace/cluster1/cluster1.yamlconfig file in an editor.
- Edit the file with your specific node and network requirements. Use the following sample config file. This quickstart doesn't use or include information about OpenID Connect (OIDC).
# gcrKeyPath: < to GCR service account key> gcrKeyPath: baremetal/gcr.json # sshPrivateKeyPath: < to SSH private key, used for node access> sshPrivateKeyPath: .ssh/id_rsa # gkeConnectAgentServiceAccountKeyPath: < to Connect agent service account key> gkeConnectAgentServiceAccountKeyPath: baremetal/connect-agent.json # gkeConnectRegisterServiceAccountKeyPath: < to Hub registration service account key> gkeConnectRegisterServiceAccountKeyPath: baremetal/connect-register.json # cloudOperationsServiceAccountKeyPath: < to Cloud Operations service account key> cloudOperationsServiceAccountKeyPath: baremetal/cloud-ops.json --- apiVersion: v1 kind: Namespace metadata: name: cluster-cluster1 --- apiVersion: baremetal.cluster.gke.io/v1 kind: Cluster metadata: name: cluster1 namespace: cluster-cluster1 spec: # Cluster type. This can be: # 1) admin: to create an admin cluster. This can later be used to create user clusters. # 2) user: to create a user cluster. Requires an existing admin cluster. # 3) hybrid: to create a hybrid cluster that runs admin cluster components and user workloads. # 4) standalone: to create a cluster that manages itself, runs user workloads, but does not manage other clusters. type: hybrid # Anthos cluster version. anthosBareMetalVersion: 1.7.1 # GKE connect configuration gkeConnect: projectID: PROJECT_ID # Control plane configuration controlPlane: nodePoolSpec: nodes: # Control plane node pools. Typically, this is either a single machine # or 3 machines if using a high availability deployment. - address: CONTROL_PLANE_NODE_IP # Cluster networking configuration clusterNetwork: # Pods specify the IP ranges from which pod networks are allocated. pods: cidrBlocks: - 192.168.0.0/16 # Services specify the network ranges from which service virtual IPs are allocated. # This can be any RFC 1918 range that does not conflict with any other IP range # in the cluster and node pool resources. services: cidrBlocks: - 172.26.232.0/24 # Load balancer configuration loadBalancer: # Load balancer mode can be either 'bundled' or 'manual'. # In 'bundled' mode a load balancer will be installed on load balancer nodes during cluster creation. # In 'manual' mode the cluster relies on a manually-configured external load balancer. mode: bundled # Load balancer port configuration ports: # Specifies the port the load balancer serves the Kubernetes control plane on. # In 'manual' mode the external load balancer must be listening on this port. controlPlaneLBPort: 443 # There are two load balancer virtual IP (VIP) addresses: one for the control plane # and one for the L7 Ingress service. The VIPs must be in the same subnet as the load balancer nodes. # These IP addresses do not correspond to physical network interfaces. vips: # ControlPlaneVIP specifies the VIP to connect to the Kubernetes API server. # This address must not be in the address pools below. controlPlaneVIP: CONTROL_PLANE_VIP # IngressVIP specifies the VIP shared by all services for ingress traffic. # Allowed only in non-admin clusters. # This address must be in the address pools below. ingressVIP: INGRESS_VIP # AddressPools is a list of non-overlapping IP ranges for the data plane load balancer. # All addresses must be in the same subnet as the load balancer nodes. # Address pool configuration is only valid for 'bundled' LB mode in non-admin clusters. # addressPools: # - name: pool1 # addresses: # # Each address must be either in the CIDR form (126.96.36.199/24) # # or range form (188.8.131.52-184.108.40.206). # - LOAD_BALANCER_ADDRESS_POOL- # A load balancer nodepool can be configured to specify nodes used for load balancing. # These nodes are part of the kubernetes cluster and run regular workloads as well as load balancers. # If the node pool config is absent then the control plane nodes are used. # Node pool configuration is only valid for 'bundled' LB mode. # nodePoolSpec: # nodes: # - address: LOAD_BALANCER_NODE_IP; # Proxy configuration # proxy: # url: http://[username:password@]domain # # A list of IPs, hostnames or domains that should not be proxied. # noProxy: # - 127.0.0.1 # - localhost # Logging and Monitoring clusterOperations: # Cloud project for logs and metrics. projectID: PROJECT_ID # Cloud location for logs and metrics. location: us-central1 # Whether collection of application logs/metrics should be enabled (in addition to # collection of system logs/metrics which correspond to system components such as # Kubernetes control plane or cluster management agents). # enableApplication: false # Storage configuration storage: # lvpNodeMounts specifies the config for local PersistentVolumes backed by mounted disks. # These disks need to be formatted and mounted by the user, which can be done before or after # cluster creation. lvpNodeMounts: # path specifies the host machine path where mounted disks will be discovered and a local PV # will be created for each mount. path: /mnt/localpv-disk # storageClassName specifies the StorageClass that PVs will be created with. The StorageClass # is created during cluster creation. storageClassName: local-disks # lvpShare specifies the config for local PersistentVolumes backed by subdirectories in a shared filesystem. # These subdirectories are automatically created during cluster creation. lvpShare: # path specifies the host machine path where subdirectories will be created on each host. A local PV # will be created for each subdirectory. path: /mnt/localpv-share # storageClassName specifies the StorageClass that PVs will be created with. The StorageClass # is created during cluster creation. storageClassName: local-shared # numPVUnderSharedPath specifies the number of subdirectories to create under path. numPVUnderSharedPath: 5 # NodeConfig specifies the configuration that applies to all nodes in the cluster. nodeConfig: # podDensity specifies the pod density configuration. podDensity: # maxPodsPerNode specifies the maximum number of pods allowed on a single node. maxPodsPerNode: 250 # containerRuntime specifies which container runtime to use for scheduling containers on nodes. # containerd and docker are supported. containerRuntime: containerd --- # Node pools for worker nodes apiVersion: baremetal.cluster.gke.io/v1 kind: NodePool metadata: name: node-pool-1 namespace: cluster-cluster1 spec: clusterName: cluster1 nodes: - address: WORKER_NODE_1_IP - address: WORKER_NODE_2_IP
Run preflight checks and create the cluster
bmctl command runs preflight checks
on your cluster config file before it creates a cluster. If the checks are successful,
bmctl creates the cluster.
To run preflight checks and create the cluster:
- Ensure that you are in the
- Use the following command to create the cluster:
./bmctl create cluster -c CLUSTER_NAMEFor example:
./bmctl create cluster -c cluster1
bmctl command monitors the preflight checks and cluster creation,
displays output to the screen, and writes verbose information
You can find the
bmctl, preflight checks, and node installation logs
in the following directory:
bmctl preflight checks the proposed cluster installation for the
- The Linux distribution and version are supported.
- SELinux is not in enforcing mode.
- For Ubuntu, AppArmor and UFW are not active.
- Google Container Registry is reachable.
- The VIPs are available.
- The cluster machines have connectivity to each other.
- Load balancer machines are on the same Layer 2 subnet.
Cluster creation can take several minutes to finish.
Get information about your cluster
After you successfully create a cluster, use the
to show information about the new cluster. During cluster creation, the
bmctl command writes a kubeconfig file for the cluster that you can
The kubeconfig file is written to
kubectl --kubeconfig bmctl-workspace/cluster1/cluster1-kubeconfig get nodes
This command returns the following output:
NAME STATUS ROLES AGE VERSION node-01 Ready master 16h v1.17.8-gke.16 node-02 Ready <none> 16h v1.17.8-gke.16
If your cluster creation fails preflight checks, then check the preflight check logs for
errors and correct them in the cluster config file. The preflight check logs are located
/log directory at the following:
The preflight check logs for each machine in the cluster are in the
CLUSTER_NAME directory and are organized by IP address.
Ignore pre-flight check errors
If your cluster creation fails after pre-flight checks, you can try to re-install the
cluster by using the
--force flag in the
--force flag installs over an existing cluster, but it ignores
the results from any preflight check failure due to already allocated server ports.
- Ensure that you are in the
- Use the following command with the
--forceflag to re-create the cluster:
./bmctl create cluster -c CLUSTER_NAME --forceFor example:
./bmctl create cluster -c cluster1 -force
Create a Deployment and a Service
Here's a custom resource definition for a Deployment:
- name: hello
Save the custom resource definition as
Create the Deployment with the following command:
kubectl --kubeconfig bmctl-workspace/cluster1/cluster1-kubeconfig create -f my-deployment.yaml
View the Deployment:
kubectl --kubeconfig bmctl-workspace/cluster1/cluster1-kubeconfig get deployments
The output shows that the Deployment has three available and ready Pods:
NAME READY UP-TO-DATE AVAILABLE AGE
my-deployment 3/3 3 3 16s
The following custom resource definition defines a Service of type LoadBalancer:
- port: 80
Save the custom resource definition as
Create the Service with the following command:
kubectl --kubeconfig bmctl-workspace/cluster1/cluster1-kubeconfig create -f my-service.yaml
View the Service:
kubectl --kubeconfig bmctl-workspace/cluster1/cluster1-kubeconfig get service my-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S
my-service LoadBalancer 172.26.232.2 172.16.1.21 80:30060/TCP
Anthos clusters on bare metal gives the service an external IP address.
Use the external IP address to call the service:
The output is a hello world message:
Hello, world! Version: 2.0.0 Hostname: my-deployment-75d45b64f9-6clxj
Create a high availability control plane
The quickstart created a simple two-node hybrid cluster. If you want to create a high availability control plane, create a cluster that has three control plane nodes.
For example, edit config file to add two additional nodes to the control plane:
controlPlane: nodePoolSpec: clusterName: cluster1 nodes: # Control Plane node pools. Typically, this is either a single machine # or 3 machines if using a high availability deployment. - address: <Machine 1 IP> - address: <Machine 2 IP> - address: <Machine 3 IP>
Run the load balancer in its own node pool
The quickstart created a simple two-node hybrid cluster. Thus, the load balancer runs on the same node that runs the control plane.
If you want the load balancer to run in its own node pool, edit the
values of the
loadBalancer section of your config file:
loadBalancer: nodePoolSpec: clusterName: "cluster1" nodes: - address: <LB Machine 1 IP> - address: <LB Machine 2 IP>