<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jisun-rea.log</title>
        <link>https://velog.io/</link>
        <description>호기심 많고 걱정도 많은 사람👻 @DevOps @Cloud</description>
        <lastBuildDate>Sat, 21 May 2022 04:57:32 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jisun-rea.log</title>
            <url>https://images.velog.io/images/jisun-rea/profile/c343963b-b370-468d-8da7-bc2fd7634b1e/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jisun-rea.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jisun-rea" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Terragrunt] local backend(tfstate 파일) 설정]]></title>
            <link>https://velog.io/@jisun-rea/Terragrunt-local-backendtfstate-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@jisun-rea/Terragrunt-local-backendtfstate-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Sat, 21 May 2022 04:57:32 GMT</pubDate>
            <description><![CDATA[<h2 id="기본-tfstate-파일-생성에-있어-terraform과-terragrunt의-차이">기본 tfstate 파일 생성에 있어 terraform과 terragrunt의 차이</h2>
<p><strong>Terraform</strong>은 backend에 대한 추가적인 설정이 없다면 기본적으로 실행 디렉토리 내에 terraform.tfstate 파일을 생성한다.
그러나, <strong>Terragrunt</strong>는 <code>backend를 따로 설정해주지 않으면 local에 tfstate파일을 생성해주지 않는다.</code></p>
<p>If Terraform has no explicit backend configuration, it creates terraform.tfstate in live directory by default. However, <code>Terragrunt doesn&#39;t</code>.</p>
<h2 id="tfstate-파일이-없으면-생기는-일">tfstate 파일이 없으면 생기는 일</h2>
<p>사실 <strong>tfstate 파일이 없어도</strong> <code>terragrunt apply로 리소스 생성이 가능</code>하고, <code>terragrunt destroy로 리소스 삭제가 가능</code>하다.</p>
<p>그럼 무엇이 문제냐, 
apply 명령으로 리소스를 생성하다 중간에 실패하였을 때, 문제 수정 후 다시 apply 명령으로 리소스를 생성하면 <code>중간에 생성 실패한 리소스부터 다시 생성을 시도하는 것이 아닌, 처음부터 이미 생성한 리소스부터 다시 생성하게 된다.</code></p>
<p>이는, terraform으로 만든 리소스에 대한 상태를 저장한 파일이 없기 때문에, terraform 입장에선 리소스가 존재하지 않는 것처럼 여겨지기 때문이다. (이것이 <code>tfstate 파일의 존재의 이유</code>이다.)</p>
<p>보통 production 환경에선 remote state 설정을 통해 tfstate 파일을 원격의 안전한 저장소(ex.s3 bucket)에 저장하도록 설정하는 것이 일반적이다. 그러나 이는 terragrunt docs에도 잘 나와있고, 여기선 해당 파일을 local에 저장시킬 수 있는 방법을 소개하겠다.</p>
<p>The thing is <code>even though tfstate file does not exist</code>, we <code>can create/destroy resources</code> using apply/destroy command.</p>
<p>But let&#39;s say we <code>failed to run apply command in the middle of creating resources.</code> For example, terraform succeed to create ec2 instance, but failed in security group.
After fixing it and run apply command again, we expect it to create resource from where it failed to create. This case, from security group.
But, terraform will create resource from the first again, from ec2 instance. 
Why? Because tfstate file stores the &#39;state&#39; of resources created by terraform, <code>without it, resources does not exist in the stance of terrform.</code> This is why state file is so important to terraform. 
<img src="https://velog.velcdn.com/images/jisun-rea/post/305d2de5-cf8f-4506-a616-e48415c0c895/image.png" alt=""></p>
<h2 id="terragrunt-local-backend-설정">Terragrunt local backend 설정</h2>
<p>terragrunt 실행 디렉토리 내에 tfstate 파일을 생성해보겠다. 실습 terragrunt 디렉토리 구조는 다음과 같다.</p>
<pre><code># config
dev
  │  common.yaml
  │  terragrunt.hcl
  │
  └─ec2
      ├─bastion
      │      terragrunt.hcl
      │
      └─tomcat
              terragrunt.hcl</code></pre><pre><code># template
aws
  └─ec2
         ec2.tf
         iam.tf
         main.tf
         output.tf
         security_group.tf
         variables.tf</code></pre><p>root terragrunt.hcl인 <code>dev/terragrunt.hcl</code> 에 아래 내용을 추가한다.</p>
<pre><code>remote_state {
  backend = &quot;local&quot;
  config = {
    path = &quot;${get_terragrunt_dir()}/terraform.tfstate&quot;
  }
}</code></pre><p>참고: <a href="https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#get_terragrunt_dir">https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#get_terragrunt_dir</a></p>
<p>그리고 실제로 리소스를 만드는 <code>template의 모듈별 main.tf</code>에 아래 내용을 추가하면 끝이다.</p>
<pre><code>terraform {
  backend &quot;local&quot; {}
}</code></pre><p><img src="https://velog.velcdn.com/images/jisun-rea/post/ac5948a3-30bb-4dd9-97ea-a9c1342a2cc4/image.png" alt=""></p>
<p>terragrunt plan - terragrunt apply 후에 다음과 같이 tfstate 파일이 생성되는 것을 확인할 수 있다. 각자의 상황에 맞춰 path를 바꿔주면 된다.</p>
<p>끝!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ELK] The index pattern associated with this object no longer exists.]]></title>
            <link>https://velog.io/@jisun-rea/ELK-The-index-pattern-associated-with-this-object-no-longer-exists</link>
            <guid>https://velog.io/@jisun-rea/ELK-The-index-pattern-associated-with-this-object-no-longer-exists</guid>
            <pubDate>Thu, 07 Apr 2022 05:46:54 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p>ELk의 Index Pattern을 수정 후 기존 visualize에서 다음과 같은 에러가 발생했다.</p>
<blockquote>
<p>The index pattern associated with this object no longer exists.</p>
</blockquote>
<p>당연히 새로운 Index를 생성했기 때문에 기존 Index id만을 바라보고 있던 시각화에서 에러가 발생한 것이다.</p>
<h1 id="해결">해결</h1>
<p>해결 방법은 새로운 Index id로 수정해주면 된다.</p>
<ol>
<li>Stack Management &gt; Kibana &gt; Index Pattern 에서 해당 index 패턴 클릭 링크의 주소에 맨 뒤에 붙어있는 id를 확인</li>
<li>시각화 에러 페이지 맨 아레 references 부분에서 <code>type이 index-pattern인 id의 값을 바꿔주면 된다.</code></li>
</ol>
<p>방법은 아래 링크를 참조할 것!</p>
<p><a href="https://discuss.elastic.co/t/visualizations-broken-after-deleting-index-pattern-resolved-the-index-pattern-associated-with-this-object-no-longer-exists/181452">https://discuss.elastic.co/t/visualizations-broken-after-deleting-index-pattern-resolved-the-index-pattern-associated-with-this-object-no-longer-exists/181452</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AWS] IAM Role, AssumeRole]]></title>
            <link>https://velog.io/@jisun-rea/AWS-IAM-Role-AssumeRole</link>
            <guid>https://velog.io/@jisun-rea/AWS-IAM-Role-AssumeRole</guid>
            <pubDate>Sat, 12 Feb 2022 06:15:49 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>iam role과 assume role에 대한 이해를 의식의 흐름대로 정리했음...🧐🥺 틀릴 수 있음 주의!</p>
</blockquote>
<h2 id="iam-role이란">IAM Role이란</h2>
<ul>
<li>여러 policy와 연결함으로써 권한을 가질 수 있다.</li>
<li>여러 객체에게 부여할 수 있다.</li>
<li>한 사람만이 user을 사용할 수 있는것과 달리</li>
<li>role은 필요로 하는 이는 누구나 사용 가능</li>
<li>단, 신뢰할 수 있는 사람만!</li>
</ul>
<h2 id="assume-role">Assume Role</h2>
<h3 id="예제-1">예제 1</h3>
<p>예를 들면, EC2에 S3를 조회하는 Role을 부여한다고 해보자.
role 정의 부분을 terraform 코드로 보면 다음과 같다.</p>
<pre><code>resource &quot;aws_iam_instance_profile&quot; &quot;bastion&quot; {
  name = &quot;iam-${local.name}-instance-profile&quot;
  role = aws_iam_role.bastion.name
}

resource &quot;aws_iam_role&quot; &quot;bastion&quot; {
  name               = &quot;iam-${local.name}-role&quot;
  path               = &quot;/ec2/&quot;
  assume_role_policy = &lt;&lt;EOF
{
  &quot;Version&quot;: &quot;2012-10-17&quot;,
  &quot;Statement&quot;: [
    {
      &quot;Action&quot;: &quot;sts:AssumeRole&quot;,
      &quot;Principal&quot;: {
        &quot;Service&quot;: [&quot;ec2.amazonaws.com&quot;]
      },
      &quot;Effect&quot;: &quot;Allow&quot;
    }
  ]
}
EOF
}

data &quot;aws_iam_policy_document&quot; &quot;bastion&quot; {
  statement {
    sid = &quot;ReadBucket&quot;

    actions = [
      &quot;s3:Get*&quot;,
      &quot;s3:List*&quot;,
    ]

    resources = [
      &quot;arn:aws:s3:::jisun-*&quot;,
    ]
  }
}

resource &quot;aws_iam_policy&quot; &quot;bastion&quot; {
  name   = &quot;iam-${local.name}-s3&quot;
  path   = &quot;/ec2/&quot;
  policy = data.aws_iam_policy_document.bastion.json
}

resource &quot;aws_iam_role_policy_attachment&quot; &quot;bastion&quot; {
  role       = aws_iam_role.bastion.id
  policy_arn = aws_iam_policy.bastion.arn
}
</code></pre><p>policy를 정의하고 이를 role에 붙이는 부분은 딱 알 수 있을 것이다.
그렇다면, <code>assume_role_policy</code> 부분의 정의는 무엇일까?</p>
<p>이 부분이 바로 해당 <code>role을 사용할 수 있는 대상을 지정</code>하는 부분이다. aws console상에선 trusted entities에서 확인할 수 있다.</p>
<p>Principal이 assume role이 allow 된다. 즉, EC2 리소스가 이 role을 사용할 수 있게 된 것이다.</p>
<p>그러면 EC2는 이 role에 대한 권한을 위임받아서 role과 연결된 policy에 대한 권한, 즉 s3를 list하고 get할 수 있는 권한을 얻게 된다.</p>
<h3 id="예제2">예제2</h3>
<p>A user에 assume role 정의
B role에 s3 list 권한 부여</p>
<p>A는 B의 권한을 위임받아서 s3 list를 할 수 있음</p>
<p>너무 좋은 사이트..!:
<a href="https://jonnung.dev/posts/2021-01-28-aws-iam-role/">https://jonnung.dev/posts/2021-01-28-aws-iam-role/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[k8s] Node Selectors, Node Affinity, Taints/Tolerations vs Node Affinity, DaemonSets, Static Pods]]></title>
            <link>https://velog.io/@jisun-rea/k8s-Node-Selectors-Node-Affinity-TaintsTolerations-vs-Node-Affinity-DaemonSets-Static-Pods</link>
            <guid>https://velog.io/@jisun-rea/k8s-Node-Selectors-Node-Affinity-TaintsTolerations-vs-Node-Affinity-DaemonSets-Static-Pods</guid>
            <pubDate>Tue, 01 Feb 2022 09:42:48 GMT</pubDate>
            <description><![CDATA[<h2 id="node-selectors">Node Selectors</h2>
<blockquote>
<p>Pod가 특정 Node에만 schedule될 수 있게 하는 것
** 그러나 multi label이라던지 복잡한 selector은 불가능</p>
</blockquote>
<p>pod-definition.yml</p>
<pre><code class="language-yaml">apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: data-processor
    image: data-processor
  nodeSelector:
    size: Large</code></pre>
<pre><code class="language-bash">kubectl label nodes &lt;node-name&gt; &lt;label-key&gt;=&lt;label-value&gt;</code></pre>
<h1 id="node-affinity">Node Affinity</h1>
<blockquote>
<p>ensure pods are hosted on particular node</p>
</blockquote>
<pre><code class="language-yaml">apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: size
            operator: In
            values:
            - large            
  containers:
  - name: nginx
    image: nginx</code></pre>
<ul>
<li>만약 large node 뿐만 아니라 small node에도 배포될 수 있게 하려면, values 밑에 small 을 추가하기만 하면 된다.</li>
</ul>
<h3 id="node-affinity-types">Node Affinity Types</h3>
<h4 id="available">Available</h4>
<ul>
<li><strong>requiredDuringSchedulingIgnoredDuringExecution</strong><ul>
<li>if matching node does not exist, the pod will not be scheduled</li>
<li>preferredDuringSchedulingIgnoredDuringExecution
  ** 위와 같은 상황에서, affinity rule을 무시하고 아무 available node에 schedule함</li>
<li>둘다 이미 pod가 node에서 실행되고 있는 와중에 node label이 변한다거나 해도 그대로 현 node에서 schedule된다.</li>
</ul>
</li>
</ul>
<h4 id="planned">Planned</h4>
<ul>
<li><strong>requiredDuringSchedulingRequiredDuringExecution</strong></li>
</ul>
<h1 id="taintstolerations-vs-node-affinity">Taints/Tolerations vs Node Affinity</h1>
<p><code>Taints/Tolerations</code>는 node에 특정 pod만 배포될 수 있도록 할 수 있고,<br><code>Node Affinity</code>로 pod가 특정 node에만 배포될 수 있도록 할 수 있다.</p>
<p>즉, <code>두개 모두 사용</code>시 특정 pod가 특정 node에만 배포되고 다른 pod는 해당 node에 배포되지 못하게 할 수 있다.</p>
<h1 id="daemonsets">DaemonSets</h1>
<blockquote>
<p>ReplicaSet과 비슷하지만 pod가 각 node에 하나씩 스케줄링되도록 한다.
항상 모든 node에 pod가 배포되는 것을 보장한다.
만약 node가 삭제되면, 해당 노드에 배포된 pod도 삭제된다.</p>
</blockquote>
<ul>
<li>UseCase<ul>
<li>Monitoring Solution</li>
<li>Logs Viewer</li>
<li>kube-proxy</li>
<li>networking</li>
</ul>
</li>
</ul>
<h1 id="static-pods">Static Pods</h1>
<blockquote>
<p>kubernetes control plane에 독립적으로, kubelet을 통해서만 관리되는 pod</p>
</blockquote>
<p>만약 pod에 문제가 생기면 kubelet이 자동으로 restart시킴</p>
<p>master node에 control plane component(api server, controller, etc.) 를 pod로 구성시키는데 사용됨</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AWS/Terraform] AWS WAF rule action : count 란?]]></title>
            <link>https://velog.io/@jisun-rea/AWSTerraform-AWS-WAF-rule-action-count-%EB%9E%80</link>
            <guid>https://velog.io/@jisun-rea/AWSTerraform-AWS-WAF-rule-action-count-%EB%9E%80</guid>
            <pubDate>Wed, 29 Dec 2021 07:42:06 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>AWS WAF도 생소한데 allow, block도 아닌 count는 뭐지..</p>
</blockquote>
<p>terraform을 사용하여 cloudfront+s3로 웹호스팅을 구성하고, 그 앞단에 waf를 둠으로써 특정 ip만 접속 가능하게 구성하는 과정에서 정리한 글이다.</p>
<p>분명히 잘 구성했다 생각했는데 <strong>cloudfront domain name으로 접속시 웹페이지가 제대로 뜨지 않았다.</strong>
그러나 waf를 걷어내면 정상적으로 동작하였는데,</p>
<p>원인은 바로 web acl에서 rule group을 지정하는 부분에서 <code>overide_action</code>을 <code>count</code>로 지정했기 때문이었다.</p>
<h2 id="aws-wafweb-application-firewall">AWS WAF(Web Application Firewall)</h2>
<p>말 그대로 <code>웹 애플리케이션 방화벽</code>으로 웹 프로토콜(HTTP) 정보를 바탕으로 차단/허용 룰을 설정한다.</p>
<h3 id="rule-action">rule action</h3>
<p>rule에 일치하는 트래픽이 들어왔을 때 어떤 액션을 취할것인지 정의하는 것이다.</p>
<ul>
<li>allow: 해당 요청을 허용한다.</li>
<li>block: 해당 요청을 거부한다.</li>
</ul>
<p>그렇다면, count란 대체 무엇일까?</p>
<h3 id="count">count</h3>
<p>count는 해당 요청을 허용할 것인지, 막을 것인지 결정하지 않는다.
rule에 매칭되는 요청이 들어오면, <code>해당 요청이 들어왔다는 것만 인지한 후 다음 순위의 rule로 해당 요청을 보내버린다.</code></p>
<p>만약 jisun-web-acl에 A rule group과 B rule group이 있다고 해보자.</p>
<ul>
<li>jisun-web-acl의 <code>default action</code>: <code>block</code></li>
<li><code>A rule group</code>의 action: <code>count</code></li>
<li><code>B rule group</code>의 action: <code>allow</code></li>
</ul>
<p>만약 <strong>A rule group에 매칭되는 요청이 들어왔다고 가정</strong>해보자.
그럼 A rule group의 action에 따라 요청을 처리할텐데, count action이므로 <strong>같은 web acl에 있는 다른 rule group에 그 결정을 맡기게 될 것</strong>이다.</p>
<p>그렇게 되면 2가지 경우의 수로 나눠서 볼 수 있다.</p>
<ol>
<li>해당 요청이 <strong>B rule group에 해당되는 경우</strong></li>
<li>해당 요청이 <strong>B rule group에 해당되지 않는 경우</strong></li>
</ol>
<p><code>1번</code>의 경우에는 B rule group의 action이 allow이므로 해당 요청은 최종적으로 <code>allow</code>될 것이다.</p>
<p>그러나 <code>2번</code>의 경우에는 요청이 B rule group에 해당되지 않으니 결국 <strong>web acl의 default action에 따라</strong> 처리됨으로 <code>block</code>될 것이다.</p>
<h2 id="count를-왜-쓰는-것일까">count를 왜 쓰는 것일까?</h2>
<p>만약 새로운 rule group을 등록했을 때 바로 allow/block action을 지정해버리면, 테스트 환경에선 상관없겠지만 실제 운영중인 환경에 적용할 시 바로 장애로 이어질 수 있다.</p>
<p>그렇기에 <code>count</code> action으로 지정해두고 <code>새로 만든 rule group에 어떤 요청이 매칭되는지 테스트</code> 후 다른 action을 지정하면 좀더 안정적으로 waf를 사용할 수 있게 된다.</p>
<p>끝!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Error] Failed getting S3 bucket: BadRequest: Bad Request >> multi-region problem]]></title>
            <link>https://velog.io/@jisun-rea/Error-Failed-getting-S3-bucket-BadRequest-Bad-Request</link>
            <guid>https://velog.io/@jisun-rea/Error-Failed-getting-S3-bucket-BadRequest-Bad-Request</guid>
            <pubDate>Sun, 26 Dec 2021 03:30:13 GMT</pubDate>
            <description><![CDATA[<p>cloudfront + s3 으로 정적인 웹호스팅을 만드는 과정에서 terraform state file로부터 s3 정보를 읽어오지 못하는 오류가 발생하였다.
분명히 존재하는 버킷인데 읽어오지 못한다는 것은 terraform이 s3를 어디 엉뚱한데서 찾고있다는 생각이 들었다.</p>
<h2 id="problem">Problem</h2>
<p>Error: Failed getting S3 bucket (버킷명): BadRequest: Bad Request
status code: 400,
...
with data.aws_s3_bucket.hosting,
on main.tf line 30, in data &quot;aws_s3_bucket&quot; &quot;hosting&quot;:
30: data &quot;aws_s3_bucket&quot; &quot;hosting&quot; {</p>
<pre><code># aws provider
provider &quot;aws&quot; {
  version = &quot;~&gt; 3.0&quot;
  region  = &quot;us-east-1&quot;
}

# S3 bucket
data &quot;aws_s3_bucket&quot; &quot;hosting&quot; {
  bucket = &quot;&lt;버킷명&gt;&quot;
}</code></pre><h2 id="why">Why</h2>
<p>region 문제였다.
cloudfront는 항상 N. Virginia에서만 사용가능하기 때문에 aws provider의 기본 region을 us-east-1으로 설정을 해두었다.
그러나 s3 bucket은 Singapore(ap-southeast-1) region에 있었고, 그렇기에 &#39;aws_s3_bucket&#39; data source에서 &#39;bucket&#39; argument만으로는 원하는 s3 bucket을 찾아가지 못한 것이었다.</p>
<h2 id="solution">Solution</h2>
<p>provider의 alias를 사용함으로써
다중 region을 구현할 수 있다.</p>
<pre><code># default aws provider
provider &quot;aws&quot; {
  version = &quot;~&gt; 3.0&quot;
  region  = &quot;us-east-1&quot;
}

# s3 alias aws provider
provider &quot;aws&quot; {
  alias = &quot;s3&quot;

  version = &quot;~&gt; 3.0&quot;
  region = &quot;ap-southeast-1&quot;
}

# S3 bucket
data &quot;aws_s3_bucket&quot; &quot;hosting&quot; {
  provider = aws.s3  # set provider

  bucket = &quot;&lt;버킷명&gt;&quot;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Amazon Linux 2] Tomcat 서비스 계정 변경]]></title>
            <link>https://velog.io/@jisun-rea/Amazon-Linux-2-Tomcat-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B3%84%EC%A0%95-%EB%B3%80%EA%B2%BD</link>
            <guid>https://velog.io/@jisun-rea/Amazon-Linux-2-Tomcat-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B3%84%EC%A0%95-%EB%B3%80%EA%B2%BD</guid>
            <pubDate>Fri, 23 Apr 2021 08:39:05 GMT</pubDate>
            <description><![CDATA[<h2 id="🧐-갑자기-든-의문점">🧐 갑자기 든 의문점</h2>
<p>tomcat의 jvm heap 메모리 사이즈를 조정하려고
실행중인 <strong>tomcat의 PID를 확인</strong>하곤 불현듯 깨달은 것이 있다.</p>
<pre><code class="language-bash">$ ps -aux | grep tomcat
root      2946  0.2 12.0 2321400 121440 ?      Sl   01:33   0:21 /usr/bin/java -Djava.util.logging.config.file=/data/was/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /data/was/tomcat/bin/bootstrap.jar:/data/was/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/data/was/tomcat -Dcatalina.home=/data/was/tomcat -Djava.io.tmpdir=/data/was/tomcat/temp org.apache.catalina.startup.Bootstrap start
ec2-user  4000  0.0  0.2 123584  2260 pts/0    S+   04:19   0:00 grep --color=auto tomcat</code></pre>
<p><strong>서비스를 실행하는 계정이 root</strong>인 것을 발견했기 때문이다.</p>
<p>그 이유는 내가 <strong>tomcat을 컴파일 설치한 후 직접 서비스 파일을 만들어서 실행</strong>시켰기 때문이다. -&gt; <a href="https://velog.io/@jisun-rea/Amazon-Linux-2-Tomcat-8.5.64-%EC%BB%B4%ED%8C%8C%EC%9D%BC-%EC%84%A4%EC%B9%98-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%93%B1%EB%A1%9D">[Amazon Linux 2] Tomcat 8.5.64 컴파일 설치 &amp; 서비스 등록</a></p>
<p>따라서, 따로 <strong>tomcat을 위한 서비스 계정과 그룹을 만들어서 등록</strong>시키는 과정을 기록하게 되었다.</p>
<h1 id="tomcat-서비스-계정-변경">Tomcat 서비스 계정 변경</h1>
<h2 id="서비스-계정과-그룹-생성">서비스 계정과 그룹 생성</h2>
<pre><code class="language-bash">sudo groupadd was
sudo useradd tomcat -G was</code></pre>
<ul>
<li>was 그룹을 생성하고,</li>
<li>tomcat 계정을 생성함과 동시에 was 그룹에 소속시킴</li>
</ul>
<h2 id="서비스-파일-수정">서비스 파일 수정</h2>
<p>서비스 파일에서 User와 Group을 수정해주자</p>
<p><code>/usr/lib/systemd/system/tomcat.service</code></p>
<blockquote>
<p>[Unit]
Description=tomcat8.5.64
After=network.target syslog.target</p>
</blockquote>
<p>[Service]
Type=forking</p>
<blockquote>
</blockquote>
<p>Environment=CATALINA_HOME=/usr/local/tomcat8/apache-tomcat-8.5.64
User=<strong>tomcat</strong>
Group=<strong>was</strong></p>
<blockquote>
</blockquote>
<p>ExecStart=/usr/local/tomcat8/apache-tomcat-8.5.64/bin/startup.sh
ExecStop=/usr/local/tomcat8/apache-tomcat-8.5.64/bin/shutdown.sh</p>
<blockquote>
</blockquote>
<p>UMask=0007
RestartSec=10
Restart=always</p>
<blockquote>
</blockquote>
<p>SuccessExitStatus=143</p>
<blockquote>
</blockquote>
<p>[Install]
WantedBy=multi-user.target</p>
<h3 id="😂-failed-to-start-tomcat-에러">😂 Failed to start tomcat 에러</h3>
<p>서비스 파일만 수정하고 데몬을 리로드했더니 <code>Failed to start tomcat8.5.65.</code> 에러가 났었다.</p>
<pre><code class="language-bash">$ sudo systemctl daemon-reload
$ sudo systemctl status tomcat

● tomcat.service - tomcat8.5.65
   Loaded: loaded (/usr/lib/systemd/system/tomcat.service; enabled; vendor preset: disabled)
   Active: activating (auto-restart) (Result: exit-code) since 금 2021-04-23 04:25:58 UTC; 3s ago
  Process: 4145 ExecStop=/data/was/tomcat/bin/shutdown.sh (code=exited, status=203/EXEC)
  Process: 4153 ExecStart=/data/was/tomcat/bin/startup.sh (code=exited, status=203/EXEC)
 Main PID: 2946 (code=exited, status=143)

 4월 23 04:25:58 ip-10-100-3-226.ap-northeast-2.compute.internal systemd[1]: tomcat.service: control process exited, code=exited status=203
 4월 23 04:25:58 ip-10-100-3-226.ap-northeast-2.compute.internal systemd[1]: Failed to start tomcat8.5.65.
 4월 23 04:25:58 ip-10-100-3-226.ap-northeast-2.compute.internal systemd[1]: Unit tomcat.service entered failed state.
 4월 23 04:25:58 ip-10-100-3-226.ap-northeast-2.compute.internal systemd[1]: tomcat.service failed.
</code></pre>
<p>이것저것 검색해보고 고민해보다가 <strong>tomcat이 설치된 경로의 소유자와 소유 그룹을 설정하지 않았다</strong>는 것을 알았다.</p>
<h2 id="tomcat-설치-경로-소유자소유그룹-변경">tomcat 설치 경로 소유자:소유그룹 변경</h2>
<pre><code class="language-bash">sudo chown -R tomcat:was /data</code></pre>
<ul>
<li>/data/was : Tomcat 설치 경로</li>
<li>/data/was-app : Tomcat Root Directory 경로</li>
</ul>
<pre><code class="language-bash">$ ls -ld /data
drwxr-xr-x 5 tomcat was 124  4월 21 08:23 /data

$ ls -l /data
drwxr-xr-x 3 tomcat was     55  4월 21 08:23 was
drwxr-xr-x 2 tomcat was    110  4월 21 08:23 was-app</code></pre>
<h2 id="daemon-reload">daemon-reload</h2>
<p>마지막으로, 변경한 서비스 설정을 반영하기 위해 데몬을 리로드 시켜주자</p>
<pre><code class="language-bash">sudo systemctl daemon-reload</code></pre>
<h1 id="😎-최종-확인">😎 최종 확인</h1>
<pre><code class="language-bash">$ sudo systemctl status tomcat
● tomcat.service - tomcat8.5.65
   Loaded: loaded (/usr/lib/systemd/system/tomcat.service; enabled; vendor preset: disabled)
   Active: active (running) since 금 2021-04-23 04:31:16 UTC; 25s ago
 Main PID: 4302 (java)
   CGroup: /system.slice/tomcat.service
           └─4302 /usr/bin/java -Djava.util.logging.config.file=/data/was/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djd...

 4월 23 04:31:16 ip-10-100-3-226.ap-northeast-2.compute.internal systemd[1]: tomcat.service holdoff time over, scheduling restart.
 4월 23 04:31:16 ip-10-100-3-226.ap-northeast-2.compute.internal systemd[1]: Starting tomcat8.5.65...
 4월 23 04:31:16 ip-10-100-3-226.ap-northeast-2.compute.internal systemd[1]: Started tomcat8.5.65.

$ ps -aux | grep tomcat
tomcat    4302 20.3 12.3 2319352 124264 ?      Sl   04:31   0:06 /usr/bin/java -Djava.util.logging.config.file=/data/was/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /data/was/tomcat/bin/bootstrap.jar:/data/was/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/data/was/tomcat -Dcatalina.home=/data/was/tomcat -Djava.io.tmpdir=/data/was/tomcat/temp org.apache.catalina.startup.Bootstrap start
ec2-user  4364  0.0  0.2 123584  2288 pts/0    S+   04:31   0:00 grep --color=auto tomcat</code></pre>
<p>끝<del>!!</del>!~!!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Amazon Linux 2] Tomcat 8.5.64 Root Directory 변경]]></title>
            <link>https://velog.io/@jisun-rea/Amazon-Linux-2-Tomcat-8.5.64-Root-Directory-%EB%B3%80%EA%B2%BD</link>
            <guid>https://velog.io/@jisun-rea/Amazon-Linux-2-Tomcat-8.5.64-Root-Directory-%EB%B3%80%EA%B2%BD</guid>
            <pubDate>Fri, 23 Apr 2021 06:04:45 GMT</pubDate>
            <description><![CDATA[<h1 id="tomcat-root-directory-변경">Tomcat Root Directory 변경</h1>
<h2 id="🧐-root-directorydocument-base-context-root란">🧐 Root Directory(=Document Base, Context Root)란</h2>
<p>web application의 기본 디렉토리를 말한다.</p>
<p>즉, 접속자가 <code>&lt;ip-addr&gt;:8080/</code> 와 같은 루트 도메인을 땅하고 쳤을 때,
서버에서 호스팅해줄 파일들이 위치하는 기본 폴더를 얘기한다.</p>
<p>기본적으로 <strong>tomcat의 디폴트 루트 디렉토리</strong>는 <code>${CATALINA_HOME}/webapps/ROOT</code> 이다.</p>
<h2 id="root-directory를-원하는-경로로-바꿔보자">Root Directory를 원하는 경로로 바꿔보자</h2>
<p><code>${CATALINA_HOME}/conf/server.xml</code> 에 <strong>루트 디렉토리 경로가 지정</strong>되어있다.</p>
<p>방법은 간단하다. Host 태그 안에 <strong>Context 태그 한줄 추가</strong>하면 된다.</p>
<h3 id="serverxml-기본">server.xml (기본)</h3>
<pre><code class="language-xml">...
&lt;Host name=&quot;localhost&quot;  appBase=&quot;webapps&quot;
            unpackWARs=&quot;true&quot; autoDeploy=&quot;true&quot;&gt;
&lt;/Host&gt;
...</code></pre>
<h3 id="serverxml-바꾼-후">server.xml (바꾼 후)</h3>
<ul>
<li><strong>/data/was-app</strong> 으로 root directory 변경</li>
</ul>
<pre><code class="language-xml">...
&lt;Host name=&quot;localhost&quot;  appBase=&quot;webapps&quot;
            unpackWARs=&quot;true&quot; autoDeploy=&quot;true&quot;&gt;
  &lt;Context path=&quot;&quot; docBase=&quot;/data/was-app&quot; reloadable=&quot;false&quot;&gt;&lt;/Context&gt;
&lt;/Host&gt;
...</code></pre>
<ul>
<li>reloadable을 false로 만든 이유는 context 변화를 tomcat이 자동으로 감지해서 적용시킬 수 있으나, 그렇게되면 컴퓨팅 리소스를 소모하기 때문에 false로 두었음</li>
</ul>
<h3 id="서비스-재시작">서비스 재시작</h3>
<pre><code class="language-bash">sudo systemctl restart tomcat</code></pre>
<p>끝~~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[k8s] PODs, ReplicaSets, Deployments, Services, Imperative and Declarative Commands]]></title>
            <link>https://velog.io/@jisun-rea/k8s-PODs-ReplicaSets-Deployments-Services-Imperative-and-Declarative-Commands</link>
            <guid>https://velog.io/@jisun-rea/k8s-PODs-ReplicaSets-Deployments-Services-Imperative-and-Declarative-Commands</guid>
            <pubDate>Fri, 02 Apr 2021 08:44:42 GMT</pubDate>
            <description><![CDATA[<h2 id="pods">PODs</h2>
<blockquote>
<p>배포 최소 단위
Pod &gt; container -&gt; 하나의 pod는 여러 containers를 가질 수 있다.
그러나 보통 pod당 하나의 container(같은 종류의)을 담는다.</p>
</blockquote>
<h3 id="pod-with-yaml">POD with YAML</h3>
<ul>
<li>apiVersion</li>
<li>kind</li>
<li>metadata</li>
<li>spec</li>
</ul>
<pre><code class="language-yaml">apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
    type: front-end
spec:
  containers:
    - name: nginx-container
      image: nginx</code></pre>
<h2 id="replicasets">ReplicaSets</h2>
<blockquote>
<p>ReplicaSet은 selector에 있는 label과 같은 pods를 모두 관리한다.
즉, replicaSet을 만들기 전에 있던 pod도 selector의 label만 같으면 replica 개수에 포함시켜 모니터링한다.</p>
</blockquote>
<pre><code class="language-yaml">apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-replicaset
  labels:
    apps: myapp
    type: front-end
spec:
  template:
    metadata:
      name: myapp-pod
      labels:
        app: myapp
        type: front-end
    spec:
      containers:
        - name: nginx-container
          image: nginx
  replicas: 3
  selector:
    matchLabels:
      type: front-end</code></pre>
<p>replicas 개수를 늘리기 위해선 2가지 방법이 있다.</p>
<ol>
<li><code>kubectl replace -f &lt;file-name&gt;</code></li>
<li><code>kubectl scale --replicas=&lt;replica-num&gt; -f &lt;file-name&gt;</code></li>
<li><code>kubectl scale --replicas=&lt;replica-num&gt; replicaset &lt;replicaset-name&gt;</code></li>
</ol>
<p>주의할 점은, kubectl scale 명령과 파일 이름을 input으로 넣어도 자동적으로 파일 안에 replicas 개수가 업데이트되지 않는다는 점이다.</p>
<h2 id="deployments">Deployments</h2>
<blockquote>
<p>Covers the replicasets roles and plus, have capability to upgrade the underlying instances seamlessly using rolling updates, undo changes, pause, and resume changes as required</p>
</blockquote>
<pre><code class="language-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
  labels:
    apps: myapp
    type: front-end
spec:
  template:
    metadata:
      name: myapp-pod
      labels:
        app: myapp
        type: front-end
    spec:
      containers:
        - name: nginx-container
          image: nginx
  replicas: 3
  selector:
    matchLabels:
      type: front-end</code></pre>
<h2 id="services">Services</h2>
<blockquote>
<p>application들을 이어주는 역할을 한다.  </p>
</blockquote>
<h3 id="service-types">Service Types</h3>
<ol>
<li><p>NodePort
내부의 pod가 node의 port를 통해 접근될 수 있게 하는 것</p>
<ul>
<li>targetPort: 타겟 pod의 port</li>
<li>port: service의 port (필수로 지정)</li>
<li>nodePort: node의 port (300000 ~ 32767)</li>
</ul>
</li>
</ol>
<pre><code class="language-yaml">apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  type: NodePort
  ports:
    - targetPort: 80
      port: 80
      nodePort: 30008
  selector:
    app: myapp
    type: front-end</code></pre>
<pre><code>* selector 필드를 통해 매칭되는 파드를 연결시켜준다.</code></pre><p>그래서, 매칭되는 여러개의 파드를 랜덤하게 load balancing하는 역할도 수행할 수 있다.
    * 만약 여러 노드에 각각 pod가 하나씩 배치되어있고, 하나의 NodePort 서비스를 만든다면, kubernetes가 자동으로 node 전체에 확장된 서비스를 만든다.
그러면 각 node의 IP와 같은 port 번호를 통해 각각의 pod에 접근이 가능하다.</p>
<ol start="2">
<li><p>ClusterIP
cluster안에 가상의 IP를 만들어서 통신할 수 있게 하는 것
여러 pod에 연결할 수 있게 single access point를 제공해주는 역할을 한다.</p>
<pre><code class="language-yaml">apiVersion: v1
kind: Service
metadata:
name: back-end
spec:
type: ClusterIP
ports:
 - targetPort: 80
   port: 80
selector:
 app: myapp
 type: front-end</code></pre>
<ul>
<li>type을 지정하지 않으면 default service로 ClusterIP로 만들어짐</li>
</ul>
</li>
<li><p>LoadBalancer
CSP에서 제공하는 로드밸런서를 사용하는 방법</p>
<ul>
<li>NodePort를 사용하면 여러 node가 존재하는 환경에서 각각의 node의 IP주소를 입력해야 접근이 가능하다.
그러나, 이런 여러 node의 IP주소를 하나로 묶어서 유저에게 접근 포인트를 제공하기 위해서는 CSP에서 제공하는 LB를 사용할 수 있는 LoadBalancer 서비스가 필요하다.</li>
</ul>
</li>
</ol>
<pre><code class="language-yaml">apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  type: LoadBalancer
  ports:
    - targetPort: 80
      port: 80
      nodePort: 30008
  selector:
    app: myapp
    type: front-end</code></pre>
<h2 id="imperative-vs-declarative">Imperative vs Declarative</h2>
<blockquote>
<p>시험에서 적절히 두가지 방법을 사용할줄 알아야한다.</p>
</blockquote>
<h3 id="imperative">Imperative</h3>
<ul>
<li>Create Objects<pre><code class="language-bash">kubectl create -f nginx.yaml</code></pre>
</li>
<li>Update Objects<pre><code class="language-bash">kubectl edit deployment nginx</code></pre>
<ul>
<li>여기서 열리는 file은 위의 local file인 nginx.yaml과 다른 파일이다.
edit 명령어로 열리는 파일은 kubernetes memory에 올라가있는 definition file로, 그 변화가 현재 살아있는 object에 적용된다.<code>bash
kubectl replace -f nginx.yaml
``````bash
kubectl replace --force -f nginx.yaml</code></li>
<li>force 옵션을 쓰면 object를 완전히 삭제하고 다시 만들게 된다.</li>
</ul>
</li>
</ul>
<h2 id="declarative">Declarative</h2>
<ul>
<li>Create Objects<pre><code class="language-bash">kubectl apply -f nginx.yaml</code></pre>
<pre><code class="language-bash">kubectl apply -f /path/to/config-files</code></pre>
</li>
<li>Update Objects<pre><code class="language-bash">kubectl apply -f nginx.yaml</code></pre>
<ul>
<li>replace와 다른점은, object가 사전에 미리 존재해있지 않다면 replace는 에러를 낸다.</li>
</ul>
</li>
</ul>
<h2 id="kubectl-apply-command">kubectl apply command</h2>
<blockquote>
<p>apply 명령을 통해 local file의 내용을 kubernetes 안의 실제 live한 object의 정의 파일에 적용시키는 역할을 한다.
또한, last applied configuration을 저장해두기 때문에 apply 명령을 통해 수정된 local file을 적용시키면 변화를 감지하여 적용할 수 있다.&gt; create 나 replace 명령어는 이런 last applied configuration을 저장하지 않는다.</p>
</blockquote>
<p>#CKA
#CKA/Core_Concepts</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[k8s] ETCD, kube-apiserver, Kube Controller Manager, Kube Scheduler, Kubelet, Kube-proxy]]></title>
            <link>https://velog.io/@jisun-rea/k8s-ETCD-kube-apiserver-Kube-Controller-Manager-Kube-Scheduler-Kubelet-Kube-proxy-PODs</link>
            <guid>https://velog.io/@jisun-rea/k8s-ETCD-kube-apiserver-Kube-Controller-Manager-Kube-Scheduler-Kubelet-Kube-proxy-PODs</guid>
            <pubDate>Fri, 02 Apr 2021 08:36:25 GMT</pubDate>
            <description><![CDATA[<h2 id="etcd">ETCD</h2>
<blockquote>
<p>distributed reliable key-value store</p>
</blockquote>
<p><code>kubectl get</code> 명령으로 보는 모든 정보가 ETCD server로부터 온 것이다.
cluster에 만든 모든 변화들이 이곳에 기록된다.</p>
<p>cluster을 어떻게 배포하느냐에 따라서 ETCD도 다르게 배포된다.</p>
<ol>
<li>scratch</li>
<li>kubeadm (CKA 환경)</li>
</ol>
<p>kubeadm으로 cluster을 구성하게 되면,
ETCD server은 kube-system namespace에 POD 형태로 배포된다.</p>
<h2 id="kube-apiserver">kube-apiserver</h2>
<blockquote>
<p>primary management component in kubernetes</p>
</blockquote>
<p>kubectl 명령어를 치면, kubectl utility가 kube-apiserver로 전달된다. 그러면, kube-apiserver은 첫번째로 요청을 인증하고 검증한다. 그리고 ETCD cluster로부터 데이터를 가져와서 돌려준다.</p>
<p>Pod를 하나 만드는 과정을 살펴보면 명확하다.</p>
<ol>
<li>user을 인증한다.</li>
<li>request 검증한다.</li>
<li>apiserver이 pod 객체를 만들고(아직 node에 할당하기 전) 이 사실을ETCD server에 업데이트하고 user에게 pod가 생성되었음을 알린다.</li>
<li>scheduler은 apiserver을 지속적으로 모니터링하고있다가 새로운 pod가 생긴것(node에는 할당되지 않은)을 알아차린다.</li>
<li>scheduler이 pod를 위치시킬 적당한 node를 확인하고 kube-apiserver에게 알리고 kube-apiserver은 이 사실을 ETCD cluster에 업데이트한다.</li>
<li>그리곤 kube-apiserver은 해당 worker node에 있는 kubelet에 해당 정보를 전달하고</li>
<li>그러면 kubelet이 해당 node에 pod를 생성하고 container runtime engine에게 application image를 배포하도록 시킨다.</li>
<li>그리고 다시 kubelet은 status를 apiserver에게 전달하고 apiserver은 정보를 다시 ETCD cluster에 업데이트한다.</li>
</ol>
<h2 id="kube-controller-manager">Kube Controller Manager</h2>
<blockquote>
<p>manages various controllers in kubernetes</p>
</blockquote>
<h3 id="controller">Controller</h3>
<blockquote>
<p>process that continuously monitors the state of various components within the system
and works towards bringing the whole system to the desired functioning state</p>
</blockquote>
<p>예를들면, node controller은 node의 상태를 검사하고 application이 running할 수 있게 만들어야하는 의무를 가지고 있다.
단, 이러한 action은 kube-apiserver을 통해 수행한다.</p>
<p>kubernetes에서 나오는 모든 개념, namespaces, replicasets, deployment 모두는 controller으로부터 나온다.</p>
<p>이런 여러 controller을 하나의 패키지로 담은 것이 kube controller manager인 셈이다.</p>
<h2 id="kube-scheduler">Kube Scheduler</h2>
<blockquote>
<p>deciding which pod goes on which node
** 실제로 pod를 node에 위치시키는건 kubelet</p>
</blockquote>
<h2 id="kubelet">Kubelet</h2>
<blockquote>
<p>register node, create pods, monitor node&amp;pods</p>
</blockquote>
<p>특이점은 kubeadm tool을 사용하면 자동적으로 설치되었던 다른 component와는 달리, kubelet은 자동으로 배포되지 않는다.
항상 직접 worker node에 kubelet을 설치해야 한다.</p>
<h2 id="kube-proxy">Kube-proxy</h2>
<blockquote>
<p>process that runs on each node in the kubernetes cluster to look for new services and every time a new service is created, it creates the appropriate rules on each node to forward traffic to those services to the backend pods</p>
</blockquote>
<p>예를들면, web pod와 db pod가 있다고 할 때, web pod는 db pod에 접근하기 위해 db pod의 ip에 직접 접근하는 것이 아니라(ip가 변할 수 있는 등의 이유 때문), db service를 통해 db pod(backend pod)에 접근한다.
여기서 kube-proxy는 iptables rule을 통해 각 node에 iptable을 만들어서 트래픽을 보낼 수 있게 만든다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Amazon Linux 2] Tomcat 8.5.64 컴파일 설치 & 서비스 등록]]></title>
            <link>https://velog.io/@jisun-rea/Amazon-Linux-2-Tomcat-8.5.64-%EC%BB%B4%ED%8C%8C%EC%9D%BC-%EC%84%A4%EC%B9%98-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%93%B1%EB%A1%9D</link>
            <guid>https://velog.io/@jisun-rea/Amazon-Linux-2-Tomcat-8.5.64-%EC%BB%B4%ED%8C%8C%EC%9D%BC-%EC%84%A4%EC%B9%98-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%93%B1%EB%A1%9D</guid>
            <pubDate>Sun, 28 Mar 2021 06:43:50 GMT</pubDate>
            <description><![CDATA[<h1 id="😉-tomcat-컴파일-설치">😉 Tomcat 컴파일 설치</h1>
<blockquote>
<p>yum과 같은 package manager 대신, 소스를 직접 다운받아 컴파일해서 설치</p>
</blockquote>
<blockquote>
<p>그런데, 톰캣은 컴파일 과정은 없고 소스파일만 받아다가 잘 위치해놓고 서비스 등록하는 것으로 끝!</p>
</blockquote>
<pre><code class="language-bash">$ sudo yum install -y java-1.8.0-openjdk-devel.x86_64

$ mkdir /usr/local/tomcat8
$ cd /usr/local/tomcat8

$ wget https://downloads.apache.org/tomcat/tomcat-8/v8.5.64/bin/apache-tomcat-8.5.64.tar.gz
$ tar xvfz apache-tomcat-8.5.64.tar.gz</code></pre>
<h1 id="😊-서비스-등록">😊 서비스 등록</h1>
<pre><code class="language-bash">$ vim /usr/lib/systemd/system/tomcat.service</code></pre>
<blockquote>
<p><strong>[Unit]</strong>
Description=tomcat8.5.64
After=network.target syslog.target</p>
</blockquote>
<p><strong>[Service]</strong>
Type=forking</p>
<blockquote>
</blockquote>
<p>Environment=CATALINA_HOME=/usr/local/tomcat8/apache-tomcat-8.5.64
User=root
Group=root</p>
<blockquote>
</blockquote>
<p>ExecStart=/usr/local/tomcat8/apache-tomcat-8.5.64/bin/startup.sh
ExecStop=/usr/local/tomcat8/apache-tomcat-8.5.64/bin/shutdown.sh</p>
<blockquote>
</blockquote>
<p>UMask=0007
RestartSec=10
Restart=always</p>
<blockquote>
</blockquote>
<p>SuccessExitStatus=143</p>
<blockquote>
</blockquote>
<p><strong>[Install]</strong>
WantedBy=multi-user.target</p>
<pre><code class="language-bash">$ systemctl start tomcat
$ systemctl enable tomcat</code></pre>
<p>이렇게 간단히 끝~~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[k8s] 소개 & 구성요소 및 API]]></title>
            <link>https://velog.io/@jisun-rea/Kubernetes-%EC%86%8C%EA%B0%9C-%EA%B5%AC%EC%84%B1%EC%9A%94%EC%86%8C-%EB%B0%8F-API</link>
            <guid>https://velog.io/@jisun-rea/Kubernetes-%EC%86%8C%EA%B0%9C-%EA%B5%AC%EC%84%B1%EC%9A%94%EC%86%8C-%EB%B0%8F-API</guid>
            <pubDate>Fri, 26 Mar 2021 05:37:35 GMT</pubDate>
            <description><![CDATA[<h1 id="kubernetesk8s란">Kubernetes(k8s)란?</h1>
<blockquote>
<p>한마디로 컨테이너를 관리하는 플랫폼이다.</p>
</blockquote>
<ul>
<li>컨테이너 플랫폼</li>
<li>마이크로서비스 플랫폼</li>
<li>이식성 있는 클라우드 플랫폼</li>
</ul>
<p><a href="https://kubernetes.io/ko/docs/concepts/overview/components/">[참고] Kubernetes docs</a></p>
<h1 id="구성요소-및-api">구성요소 및 API</h1>
<h2 id="마스터">마스터</h2>
<blockquote>
<p>클러스터의 컨트롤 플레인 제공</p>
</blockquote>
<ul>
<li><strong>API 서버(Kube-apiserver)</strong><ul>
<li>쿠버네티스 클러스터의 모든 구성요소들은 API 서버를 통해 통신함</li>
</ul>
</li>
<li><strong>etcd</strong><ul>
<li>클러스터 데이터의 키-값 저장소</li>
</ul>
</li>
<li><strong>쿠버네티스 컨트롤러 관리자(kube-controller-manager)</strong><ul>
<li>클러스터의 상태를 감시하고 필요한 상태로 이행하는 컨트롤 기능 담당<ul>
<li><strong>Node controller</strong>: 노드 상태 감시&amp;대응</li>
<li><strong>Replication controller</strong>: 복제 컨트롤러를 사용하는 모든 오브젝트 관리 &amp; Pod 유지</li>
<li><strong>Endpoint controller</strong>: Service와 Pod 연결</li>
<li><strong>Service account 및 Token controller</strong>: namespace, account, token 담당</li>
</ul>
</li>
</ul>
</li>
<li>클라우드 컨트롤러 관리자(cloud-controller-manager)</li>
</ul>
<h2 id="노드">노드</h2>
<blockquote>
<p>쿠버네티스의 컨테이너 런타임 환경 제공
즉, 실제로 일하는 애들</p>
</blockquote>
<ul>
<li><strong>kubelet</strong><ul>
<li>각 노드에서 실행되는 에이전트</li>
<li>마스터로부터 제공받은 파드의 구성정보를 받아 컨테이너의 동작을 관리</li>
</ul>
</li>
<li><strong>프록시(kube-proxy)</strong><ul>
<li>호스트 레벨의 네트워크 규칙 구성</li>
<li>외부 연결을 파드에 대한 포워딩 담당</li>
</ul>
</li>
<li><strong>컨테이너 런타임</strong><ul>
<li>컨테이너 동작을 책임지는 구성요소</li>
<li>기본적으로 도커 플랫폼 사용</li>
</ul>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>