Skip to content

Instantly share code, notes, and snippets.

@rfaita
Created May 14, 2019 13:23
Show Gist options
  • Save rfaita/f100ce38f96739a7705d544fb025cb3a to your computer and use it in GitHub Desktop.
Save rfaita/f100ce38f96739a7705d544fb025cb3a to your computer and use it in GitHub Desktop.
How to configure Spring Cloud to use Kubernetes/OpenShift

Kubernetes/OpenShift

How to configure the Spring Cloud to use Kubernetes or OpenShift

First of all, install minishift or minikube

Follow this steps:

  • Project configutaion

    • Add the follow libs to project, I recommend you to create a specfic profile to this usage, you can use k8s for example.

    • dependencies for a core project, in GAV(Group, Artefact, Version) format:

      org.springframework.cloud:spring-cloud-starter-kubernetes:${kubernetesConfig}
      org.springframework.cloud:spring-cloud-starter-kubernetes-config:${kubernetesConfig}
      
      #Versions:
      kubernetesConfig=1.0.0.RELEASE
      
      
    • dependencies for a client project, in GAV format:

      org.springframework.cloud:spring-cloud-starter-openfeign:asdsadsa
      org.springframework.cloud:spring-cloud-starter-kubernetes:${kubernetesConfig}
      org.springframework.cloud:spring-cloud-starter-kubernetes-ribbon:${kubernetesConfig}
      org.springframework.cloud:spring-cloud-starter-netflix-ribbon:${netflixRibbon}
          
      #Versions:
      kubernetesConfig=1.0.0.RELEASE
      netflixRibbon=2.1.0.RELEASE
      springOpenFeignVersion=2.0.2.RELEASE
      
      
    • Create a new configuration file for k8s profile
      Example: application-k8s.yml

      • Replace IPs of external access with a name, Example:
        url: jdbc:oracle:thin:@oracledb:1521:DB01
      • Configure the Spring Boot Actuator
      management:
        endpoint:
          restart:
            enabled: true
          health:
            enabled: true
          info:
            enabled: true
    • Create a new file for bootstrap for k8s:
      Example: bootstrap-k8s.yml

      spring:
        application:
          name: <nameofservice> #the name MUST be in lower case
        cloud:
          kubernetes:
            reload:
              strategy: refresh
              enabled: true
              mode: event
            config:
              sources:
                - name: <nameofconfigmap>
                - namespace: default
      
    • Initialize the discovery client

      package com.yourcompany.config;
      
      import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
      import org.springframework.context.annotation.Configuration;
      
      @EnableDiscoveryClient
      @Configuration
      public class DiscoveryConfig {
      }
    • Allow CORS

      @Bean
          public CorsFilter corsFilter() {
              UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
      
              CorsConfiguration config = new CorsConfiguration();
              config.setAllowCredentials(true);
              config.addAllowedOrigin("*");
              config.addAllowedHeader("*");
              config.addAllowedMethod("*");
      
              source.registerCorsConfiguration("/v2/api-docs", config);
              return new CorsFilter(source);
          }
  • Create the docker image

    • In the project create a Dockerfile in the path: src/main/docker/Dockerfile
      Exemplo: Dockerfile

      FROM openjdk:10-jdk
      
      ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS
      ENV JAVA_OPTS "-Xmx256m -Xms128m"
      
      RUN useradd -s /bin/bash nameofservice
      RUN mkdir -p /home/nameofservice
      RUN chown nameofservice:nameofservice /home/nameofservice
      
      WORKDIR /home/nameofservice
      
      ADD src/main/docker/entrypoint.sh entrypoint.sh
      ADD build/libs/*.jar app.jar
      
      RUN chmod +x *.sh
      RUN chown nameofservice:nameofservice *
      
      USER nameofservice
      WORKDIR /home/nameofservice
      
      ENTRYPOINT ["./entrypoint.sh"]
    • Create the entrypoint.sh in the some path of Dockerfile

      #!/bin/sh
      
      echo "---------------------------------OPTS------------------------------------"
      echo "JAVA_OPTS="$JAVA_OPTS
      echo "-------------------------------------------------------------------------"
      
      java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar app.jar
    • In terminal, use this commands to generate the docker image

      • Build the project.
        gradle clean build -PbuildProfile=k8s
        
        or
        mvn clean build -Pk8s
        
      • Execute this command to connect or docker daemon to minikube/minishift daemon.
        eval $(minishift docker-env)
        
      • Buuld the docker image.
        docker build . -f src/main/docker/Dockerfile -t nameofservice
        
  • Configure minikube(K8S)/minishift(OpenShift)

    • Configure ClusterRole to K8S/OpenShift Example: cluster-role.yml
      apiVersion: rbac.authorization.k8s.io/v1beta1
      kind: RoleBinding
      metadata:
        name: default
        namespace: poc
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: edit
      subjects:
        - kind: ServiceAccount
          name: default
          namespace: poc
    • Create a new namespace Example: new-namespace.yml
      {
        "kind": "Namespace",
        "apiVersion": "v1",
        "metadata": {
          "name": "new_namesapce",
          "labels": {
            "name": "new_namesapce"
          }
        }
      }
    • Create a ConfigMap for remote configuration
      Example: config-map.yml
      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: nameofconfigmap
      data:
        k8s.exemplo.message: "Hello World, coming from remote config"
    • Create a Service for external access from containers
      Exemplo: endpoints.yml
      # Service
      kind: Service
      apiVersion: v1
      metadata:
        name: oracledb
      spec:
        ports:
          - port: 1521
            targetPort: 1521
            name: "port1521"
          - port: 1515
            targetPort: 1515
            name: "port1515"
      ---
      # Mapping IPs/ports for external access from K8S/OpenShift
      kind: Endpoints
      apiVersion: v1
      metadata:
        name: oracledb
      subsets:
        - addresses:
            - ip: x.x.x.x
          ports:
            - port: 1521
              name: "port1521"
            - port: 1515
              name: "port1515"
    • Create a Service for application
      Example: nameofservice-service.yml
      #Application Pod
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nameofservice-pod
      spec:
        selector:
          matchLabels:
            app: nameofservice-pod
            tier: backend
        replicas: 1 #You can configure more replicas here
        template:
          metadata:
            labels:
              app: nameofservice-pod
              tier: backend
          spec:
            containers:
              - name: nameofservice
                image: nameofservice:latest
                imagePullPolicy: Never
                ports:
                  - containerPort: 8080
                env:
                  - name: JAVA_OPTS
                    value: "-Xmx256m -Xms128m -Dspring.profiles.active=k8s -Duser.timezone=GMT-3"
      ---
      #Define the Service for Pod
      kind: Service
      apiVersion: v1
      metadata:
        name: nameofservice
        labels:
          app: nameofservice
      spec:
        selector:
          app: nameofservice-pod
          tier: backend
        ports:
          - protocol: TCP
            port: 80
            targetPort: 8080
    • How to execute commands
      kubectl apply <file>.yml
      or
      oc apply <file>.yml
  • How to load properties from ConfigMap inside Java

    • Create a new class to load the properties
    package com.yourcompany.props;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ConfigurationProperties(prefix = "k8s.exemplo")
    public class PropertiesFromConfigMap {
    
        private String message = "default message";
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    }
  • How to create a FeignClient

    • Create a new class to be your client
    package com.yourcompany.client;
    
    import com.yourcompany.contracts.NewContract;
    import org.springframework.cloud.openfeign.FeignClient;
    
    @FeignClient(name = "nameofservice")
    public interface NewClient extends NewContract {
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment