간단한 웹서비스를 EKS에 배포 후 실제 K8S가 가지는 강점을 실험해 보는 것
│ Error: error waiting for EKS Node Group (loljoa2-eks-cluster:loljoa2-eks-node) to create:
unexpected state 'CREATE_FAILED', wanted target 'ACTIVE'. last error: 2 errors occurred: │ *
eks-b2c004f2-a3a4-5681-99b9-4f6dfce8ea3c: AsgInstanceLaunchFailures: You've reached your
quota for maximum Fleet Requests for this account. Launching EC2 instance failed. │ *
DUMMY_284e67fe-8e60-4d87-ad4a-a7a07a889c78, DUMMY_5dd1d260-40d9-4f41-
b1cc-3b7f73ef626b, DUMMY_886765c6-0893-4f66-9f7f-789ccb815de5,
DUMMY_8ed860a0-86ef-47da-8303-5c1d3b8a6667, DUMMY_903b3c1ec2c0-4179-8dfa-25d669e5da93, DUMMY_b1d5ea72-a084-4c56-b0dc-f38a40e1921b,
DUMMY_b6d9d18e-daf0-4b07-8857-525282c6569a, DUMMY_c2694c63-8c59-48e4-8465-
cc7d83ea6fc6, DUMMY_ca9ead15-3d72-4640-afdd-1d606fbacefa, DUMMY_e0aed6f8-
c0d8-4276-820d-f2f34910cfa6: NodeCreationFailure: Instances failed to join the kubernetes cluste
{"level":"error","ts":1649780740.8978348,"logger":"controllerruntime.manager.controller.ingress","msg":"Reconciler
error","name":"ingress-2000","namespace":"game-2000","error":"WebIdentityErr: failed to retrieve
credentials\ncaused by: AccessDenied: Not authorized to perform
sts:AssumeRoleWithWebIdentity\n\tstatus code: 403, request id: 4e57cee3-4945-4186-85cdd3ca033258f0"}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::04------9347:oidc-provider/oidc.eks
ap-northeast-2.amazonaws.com/id/252FEB----------------98FF9E7"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
// "oidc.eks.ap-northeast-2.amazonaws.com/id/252FEB------------98FF9E7:aud": "sts.amazonaws.com", 이부분 대치
"oidc.eks.ap-northeast-2.amazonaws.com/id/252FEB-------------98FF9E7:sub":"system:serviceaccount:kube-system:aws-load-balancercontroller"
}
}
}
]
}
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: istio # 주석이 중요함
name: ingress
spec:
rules:
- host: httpbin.example.com
http:
paths:
- path: /status/*
backend:
serviceName: httpbin
servicePort: 8000
node {
stage('Clone repository') {
checkout scm
}
stage("Build image") {
sh "mvn spring-boot:build-image -D spring.profiles.active=prod -D S3_BUCKET_NAME=loljoa-resource-bucket"
}
stage("Docker login") {
environment {
DOCKER_HUB_LOGIN = credentials('docker-hub')
}
sh 'docker login --username=$DOCKER_HUB_LOGIN_USR --password=$DOCKER_HUB_LOGIN_PSW'
}
stage("Image rename") {
sh "docker tag lck_schedule_apiserver:0.0.1-SNAPSHOT loljoa/lck_schedule_apiserver:0.0.1-SNAPSHOT"
}
stage("Image push") {
sh "docker push loljoa/lck_schedule_apiserver:0.0.1-SNAPSHOT"
}
stage("Resource cleanup") {
sh "docker image prune -a"
}
}
@RestController
@RequestMapping("/api/account")
@RequiredArgsConstructor
public class HealthController {
private final ApplicationAvailability availability;
private final ApplicationEventPublisher eventPublisher;
private final LocalHostService localHostService;
@GetMapping("/hello")
public String hello() {
return "Application State\n" +
"Liveness: " + availability.getLivenessState() + "\n" +
"Readiness" + availability.getReadinessState();
}
@GetMapping("/block") //Readiness Block
public String block() {
AvailabilityChangeEvent.publish(eventPublisher, this, ReadinessState.REFUSING_TRAFFIC);
return "Blocked requests " + localHostService.getLocalHostInfo();
}
@GetMapping("/turnoff") //Liveness Block
public String turnoff() {
AvailabilityChangeEvent.publish(eventPublisher, this, LivenessState.BROKEN);
return "Broken " + localHostService.getLocalHostInfo();
}
@Async
@EventListener
public void onStateChanged(AvailabilityChangeEvent<ReadinessState> readiness) throws InterruptedException {
System.out.println("State is changed to " + readiness.getState());
if(readiness.getState().equals(ReadinessState.REFUSING_TRAFFIC)) {
Thread.sleep(15000L)
AvailabilityChangeEvent.publish(eventPublisher, this, ReadinessState.ACCEPTING_TRAFFIC);
}
// Action When State Changed
}
}
apiVersion: v1
kind: Secret
metadata:
name: ca-key-pair
namespace: sandbox
data:
tls.crt: LS0tLS1CRUdJTi...
tls.key: LS0tLS1CRU...
$ kubectl get issuers ca-issuer -n sandbox -o wide
NAME READY STATUS AGE
ca-issuer True Signing CA verified 2m
@Override
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Retryable(value = SQLException.class, backoff = @Backoff(delay = 500))
public AccountDto.BettingData bettingToChoice(Long choiceId, Long accountId, Long leagueId, Long gameId, Long point) {
BettingChoice choice = bettingChoiceRepository.getChoiceById(choiceId);
Account better = accountRepository.getAccountById(accountId);
League league = leagueRepository.getLeagueById(leagueId);
BettingGame bettingGame = bettingGameRepository.getGameDataById(gameId);
choice.addTotalPoint(better.getUsername(), point);
better.usePoint(point);
bettingGame.addTotalPoint(point);
bettingStateRepository.save(new BettingState(choice, better, league,point));
return new AccountDto.BettingData(
gameId,
league.getLeagueName().split("vs")[0],
league.getLeagueName().split("vs")[1],
league.getWeekNum(),
league.getStartTime(),
choice.getChoiceId(),
choice.getName(),
choice.getTotalPoint(),
bettingGame.getTotalPoint(),
point
);
}
무조건 k8s를 적용하는 것이 좋다라고는 볼 수 없을 것 같다.
Jenkins 사용 시 빌드에 들어가는 운영 비용이 크게 감소 되었다.
db 클러스터링
완벽한 배포 pipeline 구축
로그(EFK) 저장