Giter VIP home page Giter VIP logo

cloudstack-cloud-controller-manager's Introduction

CloudStack Kubernetes Provider

โš ๏ธ ๐Ÿšง ๐ŸŽ Ownership of this project was transferred to the Apache foundation.
It will no longer be maintained. Please migrate to apache/cloudstack-kubernetes-provider

A Cloud Controller Manager to facilitate Kubernetes deployments on Cloudstack.

Based on the old Cloudstack provider in Kubernetes that will be removed soon.

Deployment

Kubernetes

Prebuilt containers are posted on Docker Hub.

The cloud controller is intended to be deployed as a daemon set, with on instance running on each node.

To configure API access to your CloudStack management server, you need to create a secret containing a cloudstack.ini that is suitable for your environment.

cloudstack.ini should look like this:

[Global]
api-url = <CloudStack API URL>
api-key = <CloudStack API Key>
secret-key = <CloudStack API Secret>
project-id = <CloudStack Project UUID (optional)>
zone = <CloudStack Zone Name (optional)>
ssl-no-verify = <Disable SSL certificate validation: true or false (optional)>

The access token needs to be able to fetch VM information and deploy load balancers in the project or domain where the nodes reside.

To create the secret, use the following command:

kubectl create secret generic cloudstack-secret --from-file=cloudstack.ini

You can then use the provided example deployment.yaml to deploy the controller:

kubectl apply -f deployment.yaml

Protocols

This CCM supports TCP, UDP and TCP-Proxy LoadBalancer deployments.

For UDP and Proxy Protocol support, CloudStack 4.6 or later is required.

Since kube-proxy does not support the Proxy Protocol or UDP, you should connect this directly to pods, for example by deploying a DaemonSet and setting hostNetwork: true. The service running in the pod must support the protocol.

See service.yaml for an example Service deployment and part of a suitable configuration for an ingress controller.

Node Labels

โš ๏ธ The node name must match the host name, so the controller can fetch and assign metadata from CloudStack.

It is recommended to launch kubelet with the following parameter:

--register-with-taints=node.cloudprovider.kubernetes.io/uninitialized=true:NoSchedule

This will treat the node as 'uninitialized' and cause the CCM to apply metadata labels from CloudStack automatically.

Supported labels are:

  • kubernetes.io/hostname (= the instance name)
  • beta.kubernetes.io/instance-type (= the compute offering)
  • failure-domain.beta.kubernetes.io/zone (= the zone)
  • failure-domain.beta.kubernetes.io/region (also = the zone)

It is also possible to trigger this process manually by issuing the following command:

kubectl taint nodes <my-node-without-labels> node.cloudprovider.kubernetes.io/uninitialized=true:NoSchedule

Migration Guide

There are several notable differences to the old Kubernetes CloudStack cloud provider that need to be taken into account when migrating from the old cloud provider to the standalone controller.

Load Balancer

Load balancer rule names now include the protocol in addition to the LB name and service port. This was added to distinguish tcp, udp and tcp-proxy services operating on the same port. Without this change, it would not be possible to map a service that runs on both TCP and UDP port 8000, for example.

โš ๏ธ If you have existing rules, remove them before the migration, and add them back afterwards.

If you don't do this, you will end up with duplicate rules for the same service, which won't work.

Metadata

Since the controller is now intended to be run inside a pod and not on the node, it will not be able to fetch metadata from the Virtual Router's DHCP server.

Instead, it first obtains the name of the node from Kubernetes, then fetches information from the CloudStack API.

Development

Building

Go 1.12 is required to build cloudstack-ccm.

It is recommended to build with Go module support, but dependencies are also vendored.

To build the controller with correct versioning, some build flags need to be passed. A Makefile is provided that sets these build flags to values obtained from git.

go get github.com/apache/cloudstack-kubernetes-provider
cd ${GOPATH}/src/github.com/apache/cloudstack-kubernetes-provider
make

To build the cloudstack-cloud-controller-manager container, please use the provided Dockerfile. The Makefile will also with that and properly tag the resulting container.

make docker

Testing

You need a local instance of the CloudStack Management Server or a 'real' one to connect to. The CCM supports the same cloudstack.ini configuration file format used by the cs tool, so you can simply point it to that.

./cloudstack-ccm --cloud-provider external-cloudstack --cloud-config ~/.cloudstack.ini --master k8s-apiserver

Replace k8s-apiserver with the host name of your Kubernetes development clusters's API server.

If you don't have a 'real' CloudStack installation, you can also launch a local simulator instance instead. This is very useful for dry-run testing.

Copyright

ยฉ 2018 SWISS TXT AG and the Kubernetes authors.

See LICENSE-2.0 for permitted usage.

cloudstack-cloud-controller-manager's People

Contributors

joschi36 avatar onitake avatar rohityadavcloud avatar srgoni avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

cloudstack-cloud-controller-manager's Issues

Support metadata fetching

When the CCM code was still integrated into Kubernetes, it was possible to fetch node metadata from kubelet running on the nodes.

With the separated CCM, this is no longer possible.
Modify cloudstack.go to support fetching metadata via the Cloudstack API, if possible.

Support TCP proxy protocol

When load-balancing from the Cloudstack virtual router to a Kubernetes services, the client IP is masked by the load balancer.

To address this issue, there exists a special protocol that passes the client address to the load-balanced hosts before client traffic is sent: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt

This is supported in Cloudstack since 4.6.0: apache/cloudstack#848
Ingress controllers also support this: https://github.com/containous/traefik/blob/master/docs/configuration/entrypoints.md#proxyprotocol

For compatibility with services that don't support the Proxy Protocol, this shouldn't be enabled by default. Instead, a suitable command line flag or a tag for LoadBalancer deployments should be implemented.

Can't get the deployment working

Hello,

I'd like to ask for some help.

I'm trying to make my K8S using my ACS as a provider of external IP-addresses.

So, I tried the following YAML to deploy cloud-controller-manager in my K8S cluster:


---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: cloud-controller-manager
  namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: system:cloud-controller-manager
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: cloud-controller-manager
  namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: cloud-controller-manager-config
  namespace: kube-system
data:
  cloud-config: |
    [Global]
    api-url = https://***/client/api
    api-key = ***
    secret-key = ***
    zone = ***
---
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: cloud-controller-manager
  name: cloud-controller-manager
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: cloud-controller-manager
  template:
    metadata:
      labels:
        k8s-app: cloud-controller-manager
    spec:
      serviceAccountName: cloud-controller-manager
      containers:
      - name: cloud-controller-manager
        image: swisstxt/cloudstack-cloud-controller-manager:v0.0.1
        # Command line arguments: https://kubernetes.io/docs/reference/command-line-tools-reference/cloud-controller-manager/
        command:
        - /root/cloudstack-ccm
        - --cloud-provider=external-cloudstack
        - --cloud-config=/config/cloud-config
        - --kubeconfig=/var/lib/kubelet/kubeconfig # Connection Params
        - --v=4
        volumeMounts:
        - name: config-volume
          mountPath: /config
        - name: kubeconfig-volume
          mountPath: /var/lib/kubelet/kubeconfig
        - name: kubernetes-config-volume
          mountPath: /var/lib/kubernetes
      volumes:
      - name: config-volume
        configMap:
          name: cloud-controller-manager-config
      - name: kubeconfig-volume
        hostPath:
          path: /var/lib/kubelet/kubeconfig
      - name: kubernetes-config-volume
        hostPath:
          path: /var/lib/kubernetes

All entities have been created, but then I asked K8S to show me the deployments (kubectl get deployments --namespace=kube-system) and found that cloud-controller-manager isn't ready:

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
calico-kube-controllers    1/1     1            1           2d8h
cloud-controller-manager   0/1     1            0           78m
coredns                    2/2     2            2           27h
dns-autoscaler             1/1     1            1           2d8h
kubernetes-dashboard       1/1     1            1           2d8h

I asked to show me the details (kubectl describe deployment cloud-controller-manager --namespace=kube-system) and got the following:

Name:                   cloud-controller-manager
Namespace:              kube-system
CreationTimestamp:      Tue, 11 Jun 2019 17:14:07 +0300
Labels:                 k8s-app=cloud-controller-manager
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               k8s-app=cloud-controller-manager
Replicas:               1 desired | 1 updated | 1 total | 0 available | 1 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:           k8s-app=cloud-controller-manager
  Service Account:  cloud-controller-manager
  Containers:
   cloud-controller-manager:
    Image:      swisstxt/cloudstack-cloud-controller-manager:v0.0.1
    Port:       <none>
    Host Port:  <none>
    Command:
      /root/cloudstack-ccm
      --cloud-provider=external-cloudstack
      --cloud-config=/config/cloud-config
      --kubeconfig=/var/lib/kubelet/kubeconfig
      --v=4
    Environment:  <none>
    Mounts:
      /config from config-volume (rw)
      /var/lib/kubelet/kubeconfig from kubeconfig-volume (rw)
      /var/lib/kubernetes from kubernetes-config-volume (rw)
  Volumes:
   config-volume:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      cloud-controller-manager-config
    Optional:  false
   kubeconfig-volume:
    Type:          HostPath (bare host directory volume)
    Path:          /var/lib/kubelet/kubeconfig
    HostPathType:
   kubernetes-config-volume:
    Type:          HostPath (bare host directory volume)
    Path:          /var/lib/kubernetes
    HostPathType:
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Progressing    True    NewReplicaSetAvailable
  Available      False   MinimumReplicasUnavailable
OldReplicaSets:  <none>
NewReplicaSet:   cloud-controller-manager-6d6c67cdc6 (1/1 replicas created)
Events:          <none>

I found the pod and asked to give me more details on that (kubectl describe pod cloud-controller-manager-6d6c67cdc6-6xw7t --namespace=kube-system), got the following:

Name:               cloud-controller-manager-6d6c67cdc6-6xw7t
Namespace:          kube-system
Priority:           0
PriorityClassName:  <none>
Node:               node2/10.13.17.2
Start Time:         Tue, 11 Jun 2019 17:14:07 +0300
Labels:             k8s-app=cloud-controller-manager
                    pod-template-hash=6d6c67cdc6
Annotations:        <none>
Status:             Running
IP:                 10.233.96.2
Controlled By:      ReplicaSet/cloud-controller-manager-6d6c67cdc6
Containers:
  cloud-controller-manager:
    Container ID:  docker://22accff626f0c2978a2441757a35fd61d4aae4316e90b06a78aa7e57b6dd9194
    Image:         swisstxt/cloudstack-cloud-controller-manager:v0.0.1
    Image ID:      docker-pullable://swisstxt/cloudstack-cloud-controller-manager@sha256:baf7713f96295f1c7ebdfc44076853aa9e07318ae9371c762ad04a840a4ef55f
    Port:          <none>
    Host Port:     <none>
    Command:
      /root/cloudstack-ccm
      --cloud-provider=external-cloudstack
      --cloud-config=/config/cloud-config
      --kubeconfig=/var/lib/kubelet/kubeconfig
      --v=4
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1
      Started:      Tue, 11 Jun 2019 18:37:27 +0300
      Finished:     Tue, 11 Jun 2019 18:37:29 +0300
    Ready:          False
    Restart Count:  21
    Environment:    <none>
    Mounts:
      /config from config-volume (rw)
      /var/lib/kubelet/kubeconfig from kubeconfig-volume (rw)
      /var/lib/kubernetes from kubernetes-config-volume (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from cloud-controller-manager-token-2nkzq (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             False
  ContainersReady   False
  PodScheduled      True
Volumes:
  config-volume:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      cloud-controller-manager-config
    Optional:  false
  kubeconfig-volume:
    Type:          HostPath (bare host directory volume)
    Path:          /var/lib/kubelet/kubeconfig
    HostPathType:
  kubernetes-config-volume:
    Type:          HostPath (bare host directory volume)
    Path:          /var/lib/kubernetes
    HostPathType:
  cloud-controller-manager-token-2nkzq:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  cloud-controller-manager-token-2nkzq
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason   Age                    From            Message
  ----     ------   ----                   ----            -------
  Warning  BackOff  3m12s (x361 over 83m)  kubelet, node2  Back-off restarting failed container

And, finally, I asked for the logs (kubectl logs cloud-controller-manager-6d6c67cdc6-6xw7t --namespace=kube-system), found that:

I0611 15:37:27.446096       1 flags.go:33] FLAG: --address="0.0.0.0"
I0611 15:37:27.446554       1 flags.go:33] FLAG: --allocate-node-cidrs="false"
I0611 15:37:27.446581       1 flags.go:33] FLAG: --allow-untagged-cloud="false"
I0611 15:37:27.446600       1 flags.go:33] FLAG: --alsologtostderr="false"
I0611 15:37:27.446634       1 flags.go:33] FLAG: --authentication-kubeconfig=""
I0611 15:37:27.446656       1 flags.go:33] FLAG: --authentication-skip-lookup="false"
I0611 15:37:27.446676       1 flags.go:33] FLAG: --authentication-token-webhook-cache-ttl="10s"
I0611 15:37:27.446701       1 flags.go:33] FLAG: --authorization-always-allow-paths="[/healthz]"
I0611 15:37:27.446735       1 flags.go:33] FLAG: --authorization-kubeconfig=""
I0611 15:37:27.446753       1 flags.go:33] FLAG: --authorization-webhook-cache-authorized-ttl="10s"
I0611 15:37:27.446773       1 flags.go:33] FLAG: --authorization-webhook-cache-unauthorized-ttl="10s"
I0611 15:37:27.446791       1 flags.go:33] FLAG: --bind-address="0.0.0.0"
I0611 15:37:27.446811       1 flags.go:33] FLAG: --cert-dir=""
I0611 15:37:27.446828       1 flags.go:33] FLAG: --cidr-allocator-type="RangeAllocator"
I0611 15:37:27.446845       1 flags.go:33] FLAG: --client-ca-file=""
I0611 15:37:27.446865       1 flags.go:33] FLAG: --cloud-config="/config/cloud-config"
I0611 15:37:27.446885       1 flags.go:33] FLAG: --cloud-provider="external-cloudstack"
I0611 15:37:27.446903       1 flags.go:33] FLAG: --cluster-cidr=""
I0611 15:37:27.446921       1 flags.go:33] FLAG: --cluster-name="kubernetes"
I0611 15:37:27.446938       1 flags.go:33] FLAG: --concurrent-service-syncs="1"
I0611 15:37:27.446960       1 flags.go:33] FLAG: --configure-cloud-routes="true"
I0611 15:37:27.446981       1 flags.go:33] FLAG: --contention-profiling="false"
I0611 15:37:27.447001       1 flags.go:33] FLAG: --controller-start-interval="0s"
I0611 15:37:27.447020       1 flags.go:33] FLAG: --controllers="[*]"
I0611 15:37:27.447043       1 flags.go:33] FLAG: --external-cloud-volume-plugin=""
I0611 15:37:27.447059       1 flags.go:33] FLAG: --feature-gates=""
I0611 15:37:27.447081       1 flags.go:33] FLAG: --help="false"
I0611 15:37:27.447098       1 flags.go:33] FLAG: --http2-max-streams-per-connection="0"
I0611 15:37:27.447117       1 flags.go:33] FLAG: --kube-api-burst="30"
I0611 15:37:27.447131       1 flags.go:33] FLAG: --kube-api-content-type="application/vnd.kubernetes.protobuf"
I0611 15:37:27.447152       1 flags.go:33] FLAG: --kube-api-qps="20"
I0611 15:37:27.447174       1 flags.go:33] FLAG: --kubeconfig="/var/lib/kubelet/kubeconfig"
I0611 15:37:27.447191       1 flags.go:33] FLAG: --leader-elect="true"
I0611 15:37:27.447207       1 flags.go:33] FLAG: --leader-elect-lease-duration="15s"
I0611 15:37:27.447224       1 flags.go:33] FLAG: --leader-elect-renew-deadline="10s"
I0611 15:37:27.447241       1 flags.go:33] FLAG: --leader-elect-resource-lock="endpoints"
I0611 15:37:27.447257       1 flags.go:33] FLAG: --leader-elect-retry-period="2s"
I0611 15:37:27.447273       1 flags.go:33] FLAG: --log-backtrace-at=":0"
I0611 15:37:27.447294       1 flags.go:33] FLAG: --log-dir=""
I0611 15:37:27.447313       1 flags.go:33] FLAG: --log-file=""
I0611 15:37:27.447332       1 flags.go:33] FLAG: --log-flush-frequency="5s"
I0611 15:37:27.447351       1 flags.go:33] FLAG: --logtostderr="true"
I0611 15:37:27.447369       1 flags.go:33] FLAG: --master=""
I0611 15:37:27.447387       1 flags.go:33] FLAG: --min-resync-period="12h0m0s"
I0611 15:37:27.447408       1 flags.go:33] FLAG: --node-monitor-period="5s"
I0611 15:37:27.447464       1 flags.go:33] FLAG: --node-status-update-frequency="5m0s"
I0611 15:37:27.447484       1 flags.go:33] FLAG: --node-sync-period="0s"
I0611 15:37:27.447501       1 flags.go:33] FLAG: --port="0"
I0611 15:37:27.447531       1 flags.go:33] FLAG: --profiling="false"
I0611 15:37:27.447550       1 flags.go:33] FLAG: --requestheader-allowed-names="[]"
I0611 15:37:27.447578       1 flags.go:33] FLAG: --requestheader-client-ca-file=""
I0611 15:37:27.447597       1 flags.go:33] FLAG: --requestheader-extra-headers-prefix="[x-remote-extra-]"
I0611 15:37:27.447633       1 flags.go:33] FLAG: --requestheader-group-headers="[x-remote-group]"
I0611 15:37:27.447671       1 flags.go:33] FLAG: --requestheader-username-headers="[x-remote-user]"
I0611 15:37:27.447694       1 flags.go:33] FLAG: --route-reconciliation-period="10s"
I0611 15:37:27.447709       1 flags.go:33] FLAG: --secure-port="10258"
I0611 15:37:27.447725       1 flags.go:33] FLAG: --skip-headers="false"
I0611 15:37:27.447743       1 flags.go:33] FLAG: --stderrthreshold="2"
I0611 15:37:27.447759       1 flags.go:33] FLAG: --tls-cert-file=""
I0611 15:37:27.447775       1 flags.go:33] FLAG: --tls-cipher-suites="[]"
I0611 15:37:27.447799       1 flags.go:33] FLAG: --tls-min-version=""
I0611 15:37:27.447815       1 flags.go:33] FLAG: --tls-private-key-file=""
I0611 15:37:27.447831       1 flags.go:33] FLAG: --tls-sni-cert-key="[]"
I0611 15:37:27.447852       1 flags.go:33] FLAG: --use-service-account-credentials="false"
I0611 15:37:27.447870       1 flags.go:33] FLAG: --v="4"
I0611 15:37:27.447886       1 flags.go:33] FLAG: --version="false"
I0611 15:37:27.447907       1 flags.go:33] FLAG: --vmodule=""
I0611 15:37:27.951849       1 serving.go:318] Generated self-signed cert in-memory
Error loading config file "/var/lib/kubelet/kubeconfig": read /var/lib/kubelet/kubeconfig: is a directory

The very last line makes me wonder, is everything correct? Yes, /var/lib/kubelet/kubeconfig is a directory on the node, and it's empty. Shouldn't it be empty? Moreover, in the deployment configuration we asked for the following:

        command:
        - /root/cloudstack-ccm
        - --cloud-provider=external-cloudstack
        - --cloud-config=/config/cloud-config
        - --kubeconfig=/var/lib/kubelet/kubeconfig # Connection Params
        - --v=4

Shouldn't we have set --kubeconfig to some filename instead of a directory's name?

Would you be so kind as to help me to understand what am I doing wrong?

Thanks in advance!

Prepare cloud provider to be included with Kubernetes

Quote from https://groups.google.com/forum/?hl=en#!topic/kubernetes-sig-architecture/soeIadIeMCs :

I did want to shed some more light on the pre-requisites for cloud providers that we have established so far (based on KEP-4 ):

  • provider has external repo with working out-of-tree cloud provider implementation
  • there are real user experience reports for that cloud provider
  • provider is reporting test grid results based on KEP-18
  • provider has docs based on KEP-19
  • tech leads of the subproject are members of the Kubernetes org (showing a level of commitment to the Kubernetes ecosystem)

Changing from TCP to TCP Proxy doesn't work

I tried changing from TCP to TCP-Proxy (with annotation).
service.beta.kubernetes.io/cloudstack-load-balancer-proxy-protocol: enabled

Trying this ensuring the loadbalancer failed with:

"Error creating load balancer (will retry): failed to ensure load balancer for service kube-system/traefik-ingress-service: error creating load balancer rule a9a6465af03a211e9886a02001c1a00c-tcp-proxy-80: CloudStack API error 537 (CSExceptionErrorCode: 9999): The range specified, 80-80, conflicts with rule 37282 which has 80-80*

Likely the API Call "create" is called and not "edit".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.