How to configure the Spring Cloud to use Kubernetes or OpenShift
First of all, install minishift or minikube
Follow this steps:
-
-
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
- Replace IPs of external access with a name, Example:
-
Create a new file for bootstrap for k8s:
Example: bootstrap-k8s.ymlspring: 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); }
-
-
-
In the project create a Dockerfile in the path: src/main/docker/Dockerfile
Exemplo: DockerfileFROM 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.
orgradle clean build -PbuildProfile=k8s
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
- Build the project.
-
-
- 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
or
kubectl apply <file>.yml
oc apply <file>.yml
- Configure ClusterRole to K8S/OpenShift
Example: cluster-role.yml
-
- 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; } }
-
- 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 { }